1/* 2 * ng_sppp.c Netgraph to Sppp module. 3 */ 4 5/*- 6 * Copyright (C) 2002-2004 Cronyx Engineering. 7 * Copyright (C) 2002-2004 Roman Kurakin <rik@cronyx.ru> 8 * 9 * This software is distributed with NO WARRANTIES, not even the implied 10 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Authors grant any other persons or organisations a permission to use, 13 * modify and redistribute this software in source and binary forms, 14 * as long as this message is kept with the software, all derivative 15 * works or modified versions. 16 * 17 * Cronyx Id: ng_sppp.c,v 1.1.2.10 2004/03/01 15:17:21 rik Exp $ 18 */ 19#include <sys/cdefs.h>
| 1/* 2 * ng_sppp.c Netgraph to Sppp module. 3 */ 4 5/*- 6 * Copyright (C) 2002-2004 Cronyx Engineering. 7 * Copyright (C) 2002-2004 Roman Kurakin <rik@cronyx.ru> 8 * 9 * This software is distributed with NO WARRANTIES, not even the implied 10 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Authors grant any other persons or organisations a permission to use, 13 * modify and redistribute this software in source and binary forms, 14 * as long as this message is kept with the software, all derivative 15 * works or modified versions. 16 * 17 * Cronyx Id: ng_sppp.c,v 1.1.2.10 2004/03/01 15:17:21 rik Exp $ 18 */ 19#include <sys/cdefs.h>
|
20__FBSDID("$FreeBSD: head/sys/netgraph/ng_sppp.c 155016 2006-01-29 22:06:51Z rik $");
| 20__FBSDID("$FreeBSD: head/sys/netgraph/ng_sppp.c 165632 2006-12-29 13:59:50Z jhb $");
|
21 22#include <sys/param.h> 23#include <sys/systm.h> 24#include <sys/errno.h> 25#include <sys/kernel.h> 26#include <sys/malloc.h> 27#include <sys/mbuf.h> 28#include <sys/errno.h> 29#include <sys/sockio.h> 30#include <sys/socket.h> 31#include <sys/syslog.h> 32#include <sys/libkern.h> 33 34#include <net/if.h> 35#include <net/if_types.h> 36#include <net/bpf.h> 37#include <net/if_sppp.h> 38 39#include <netinet/in.h> 40 41#include <netgraph/ng_message.h> 42#include <netgraph/netgraph.h> 43#include <netgraph/ng_parse.h> 44#include <netgraph/ng_sppp.h> 45 46#ifdef NG_SEPARATE_MALLOC 47MALLOC_DEFINE(M_NETGRAPH_SPPP, "netgraph_sppp", "netgraph sppp node "); 48#else 49#define M_NETGRAPH_SPPP M_NETGRAPH 50#endif 51 52/* Node private data */ 53struct ng_sppp_private { 54 struct ifnet *ifp; /* Our interface */ 55 int unit; /* Interface unit number */ 56 node_p node; /* Our netgraph node */ 57 hook_p hook; /* Hook */ 58}; 59typedef struct ng_sppp_private *priv_p; 60 61/* Interface methods */ 62static void ng_sppp_start (struct ifnet *ifp); 63static int ng_sppp_ioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 64 65/* Netgraph methods */ 66static ng_constructor_t ng_sppp_constructor; 67static ng_rcvmsg_t ng_sppp_rcvmsg; 68static ng_shutdown_t ng_sppp_shutdown; 69static ng_newhook_t ng_sppp_newhook; 70static ng_rcvdata_t ng_sppp_rcvdata; 71static ng_disconnect_t ng_sppp_disconnect; 72 73/* List of commands and how to convert arguments to/from ASCII */ 74static const struct ng_cmdlist ng_sppp_cmds[] = { 75 { 76 NGM_SPPP_COOKIE, 77 NGM_SPPP_GET_IFNAME, 78 "getifname", 79 NULL, 80 &ng_parse_string_type 81 }, 82 { 0 } 83}; 84 85/* Node type descriptor */ 86static struct ng_type typestruct = { 87 .version = NG_ABI_VERSION, 88 .name = NG_SPPP_NODE_TYPE, 89 .constructor = ng_sppp_constructor, 90 .rcvmsg = ng_sppp_rcvmsg, 91 .shutdown = ng_sppp_shutdown, 92 .newhook = ng_sppp_newhook, 93 .rcvdata = ng_sppp_rcvdata, 94 .disconnect = ng_sppp_disconnect, 95 .cmdlist = ng_sppp_cmds, 96}; 97NETGRAPH_INIT(sppp, &typestruct); 98 99MODULE_DEPEND (ng_sppp, sppp, 1, 1, 1); 100 101/* We keep a bitmap indicating which unit numbers are free. 102 Zero means the unit number is free, one means it's taken. */ 103static unsigned char *ng_sppp_units = NULL; 104static unsigned char ng_sppp_units_len = 0; 105static unsigned char ng_units_in_use = 0; 106 107/* 108 * Find the first free unit number for a new interface. 109 * Increase the size of the unit bitmap as necessary. 110 */ 111static __inline int 112ng_sppp_get_unit (int *unit) 113{ 114 int index, bit; 115 unsigned char mask; 116 117 for (index = 0; index < ng_sppp_units_len 118 && ng_sppp_units[index] == 0xFF; index++); 119 if (index == ng_sppp_units_len) { /* extend array */ 120 unsigned char *newarray; 121 int newlen; 122 123 newlen = (2 * ng_sppp_units_len) + sizeof (*ng_sppp_units); 124 MALLOC (newarray, unsigned char *, 125 newlen * sizeof (*ng_sppp_units), M_NETGRAPH_SPPP, M_NOWAIT); 126 if (newarray == NULL) 127 return (ENOMEM); 128 bcopy (ng_sppp_units, newarray, 129 ng_sppp_units_len * sizeof (*ng_sppp_units)); 130 bzero (newarray + ng_sppp_units_len, 131 newlen - ng_sppp_units_len); 132 if (ng_sppp_units != NULL) 133 FREE (ng_sppp_units, M_NETGRAPH_SPPP); 134 ng_sppp_units = newarray; 135 ng_sppp_units_len = newlen; 136 } 137 mask = ng_sppp_units[index]; 138 for (bit = 0; (mask & 1) != 0; bit++) 139 mask >>= 1; 140 KASSERT ((bit >= 0 && bit < NBBY), 141 ("%s: word=%d bit=%d", __func__, ng_sppp_units[index], bit)); 142 ng_sppp_units[index] |= (1 << bit); 143 *unit = (index * NBBY) + bit; 144 ng_units_in_use++; 145 return (0); 146} 147 148/* 149 * Free a no longer needed unit number. 150 */ 151static __inline void 152ng_sppp_free_unit (int unit) 153{ 154 int index, bit; 155 156 index = unit / NBBY; 157 bit = unit % NBBY; 158 KASSERT (index < ng_sppp_units_len, 159 ("%s: unit=%d len=%d", __func__, unit, ng_sppp_units_len)); 160 KASSERT ((ng_sppp_units[index] & (1 << bit)) != 0, 161 ("%s: unit=%d is free", __func__, unit)); 162 ng_sppp_units[index] &= ~(1 << bit); 163 164 ng_units_in_use--; 165 if (ng_units_in_use == 0) { 166 FREE (ng_sppp_units, M_NETGRAPH_SPPP); 167 ng_sppp_units_len = 0; 168 ng_sppp_units = NULL; 169 } 170} 171 172/************************************************************************ 173 INTERFACE STUFF 174 ************************************************************************/ 175 176/* 177 * Process an ioctl for the interface 178 */ 179static int 180ng_sppp_ioctl (struct ifnet *ifp, u_long command, caddr_t data) 181{ 182 int error = 0; 183 184 error = sppp_ioctl (ifp, command, data); 185 if (error) 186 return error; 187 188 return error; 189} 190 191/* 192 * This routine should never be called 193 */ 194 195static void 196ng_sppp_start (struct ifnet *ifp) 197{ 198 struct mbuf *m; 199 int len, error = 0; 200 priv_p priv = ifp->if_softc; 201 202 /* Check interface flags */ 203 /* 204 * This has side effects. It is not good idea to stop sending if we 205 * are not UP. If we are not running we still want to send LCP term 206 * packets. 207 */ 208/* if (!((ifp->if_flags & IFF_UP) && */ 209/* (ifp->if_drv_flags & IFF_DRV_RUNNING))) { */ 210/* return;*/ 211/* }*/ 212 213 if (ifp->if_drv_flags & IFF_DRV_OACTIVE) 214 return; 215 216 if (!priv->hook) 217 return; 218 219 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 220 221 while ((m = sppp_dequeue (ifp)) != NULL) {
| 21 22#include <sys/param.h> 23#include <sys/systm.h> 24#include <sys/errno.h> 25#include <sys/kernel.h> 26#include <sys/malloc.h> 27#include <sys/mbuf.h> 28#include <sys/errno.h> 29#include <sys/sockio.h> 30#include <sys/socket.h> 31#include <sys/syslog.h> 32#include <sys/libkern.h> 33 34#include <net/if.h> 35#include <net/if_types.h> 36#include <net/bpf.h> 37#include <net/if_sppp.h> 38 39#include <netinet/in.h> 40 41#include <netgraph/ng_message.h> 42#include <netgraph/netgraph.h> 43#include <netgraph/ng_parse.h> 44#include <netgraph/ng_sppp.h> 45 46#ifdef NG_SEPARATE_MALLOC 47MALLOC_DEFINE(M_NETGRAPH_SPPP, "netgraph_sppp", "netgraph sppp node "); 48#else 49#define M_NETGRAPH_SPPP M_NETGRAPH 50#endif 51 52/* Node private data */ 53struct ng_sppp_private { 54 struct ifnet *ifp; /* Our interface */ 55 int unit; /* Interface unit number */ 56 node_p node; /* Our netgraph node */ 57 hook_p hook; /* Hook */ 58}; 59typedef struct ng_sppp_private *priv_p; 60 61/* Interface methods */ 62static void ng_sppp_start (struct ifnet *ifp); 63static int ng_sppp_ioctl (struct ifnet *ifp, u_long cmd, caddr_t data); 64 65/* Netgraph methods */ 66static ng_constructor_t ng_sppp_constructor; 67static ng_rcvmsg_t ng_sppp_rcvmsg; 68static ng_shutdown_t ng_sppp_shutdown; 69static ng_newhook_t ng_sppp_newhook; 70static ng_rcvdata_t ng_sppp_rcvdata; 71static ng_disconnect_t ng_sppp_disconnect; 72 73/* List of commands and how to convert arguments to/from ASCII */ 74static const struct ng_cmdlist ng_sppp_cmds[] = { 75 { 76 NGM_SPPP_COOKIE, 77 NGM_SPPP_GET_IFNAME, 78 "getifname", 79 NULL, 80 &ng_parse_string_type 81 }, 82 { 0 } 83}; 84 85/* Node type descriptor */ 86static struct ng_type typestruct = { 87 .version = NG_ABI_VERSION, 88 .name = NG_SPPP_NODE_TYPE, 89 .constructor = ng_sppp_constructor, 90 .rcvmsg = ng_sppp_rcvmsg, 91 .shutdown = ng_sppp_shutdown, 92 .newhook = ng_sppp_newhook, 93 .rcvdata = ng_sppp_rcvdata, 94 .disconnect = ng_sppp_disconnect, 95 .cmdlist = ng_sppp_cmds, 96}; 97NETGRAPH_INIT(sppp, &typestruct); 98 99MODULE_DEPEND (ng_sppp, sppp, 1, 1, 1); 100 101/* We keep a bitmap indicating which unit numbers are free. 102 Zero means the unit number is free, one means it's taken. */ 103static unsigned char *ng_sppp_units = NULL; 104static unsigned char ng_sppp_units_len = 0; 105static unsigned char ng_units_in_use = 0; 106 107/* 108 * Find the first free unit number for a new interface. 109 * Increase the size of the unit bitmap as necessary. 110 */ 111static __inline int 112ng_sppp_get_unit (int *unit) 113{ 114 int index, bit; 115 unsigned char mask; 116 117 for (index = 0; index < ng_sppp_units_len 118 && ng_sppp_units[index] == 0xFF; index++); 119 if (index == ng_sppp_units_len) { /* extend array */ 120 unsigned char *newarray; 121 int newlen; 122 123 newlen = (2 * ng_sppp_units_len) + sizeof (*ng_sppp_units); 124 MALLOC (newarray, unsigned char *, 125 newlen * sizeof (*ng_sppp_units), M_NETGRAPH_SPPP, M_NOWAIT); 126 if (newarray == NULL) 127 return (ENOMEM); 128 bcopy (ng_sppp_units, newarray, 129 ng_sppp_units_len * sizeof (*ng_sppp_units)); 130 bzero (newarray + ng_sppp_units_len, 131 newlen - ng_sppp_units_len); 132 if (ng_sppp_units != NULL) 133 FREE (ng_sppp_units, M_NETGRAPH_SPPP); 134 ng_sppp_units = newarray; 135 ng_sppp_units_len = newlen; 136 } 137 mask = ng_sppp_units[index]; 138 for (bit = 0; (mask & 1) != 0; bit++) 139 mask >>= 1; 140 KASSERT ((bit >= 0 && bit < NBBY), 141 ("%s: word=%d bit=%d", __func__, ng_sppp_units[index], bit)); 142 ng_sppp_units[index] |= (1 << bit); 143 *unit = (index * NBBY) + bit; 144 ng_units_in_use++; 145 return (0); 146} 147 148/* 149 * Free a no longer needed unit number. 150 */ 151static __inline void 152ng_sppp_free_unit (int unit) 153{ 154 int index, bit; 155 156 index = unit / NBBY; 157 bit = unit % NBBY; 158 KASSERT (index < ng_sppp_units_len, 159 ("%s: unit=%d len=%d", __func__, unit, ng_sppp_units_len)); 160 KASSERT ((ng_sppp_units[index] & (1 << bit)) != 0, 161 ("%s: unit=%d is free", __func__, unit)); 162 ng_sppp_units[index] &= ~(1 << bit); 163 164 ng_units_in_use--; 165 if (ng_units_in_use == 0) { 166 FREE (ng_sppp_units, M_NETGRAPH_SPPP); 167 ng_sppp_units_len = 0; 168 ng_sppp_units = NULL; 169 } 170} 171 172/************************************************************************ 173 INTERFACE STUFF 174 ************************************************************************/ 175 176/* 177 * Process an ioctl for the interface 178 */ 179static int 180ng_sppp_ioctl (struct ifnet *ifp, u_long command, caddr_t data) 181{ 182 int error = 0; 183 184 error = sppp_ioctl (ifp, command, data); 185 if (error) 186 return error; 187 188 return error; 189} 190 191/* 192 * This routine should never be called 193 */ 194 195static void 196ng_sppp_start (struct ifnet *ifp) 197{ 198 struct mbuf *m; 199 int len, error = 0; 200 priv_p priv = ifp->if_softc; 201 202 /* Check interface flags */ 203 /* 204 * This has side effects. It is not good idea to stop sending if we 205 * are not UP. If we are not running we still want to send LCP term 206 * packets. 207 */ 208/* if (!((ifp->if_flags & IFF_UP) && */ 209/* (ifp->if_drv_flags & IFF_DRV_RUNNING))) { */ 210/* return;*/ 211/* }*/ 212 213 if (ifp->if_drv_flags & IFF_DRV_OACTIVE) 214 return; 215 216 if (!priv->hook) 217 return; 218 219 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 220 221 while ((m = sppp_dequeue (ifp)) != NULL) {
|
222 if (ifp->if_bpf) 223 BPF_MTAP (ifp, m);
| 222 BPF_MTAP (ifp, m);
|
224 len = m->m_pkthdr.len; 225 226 NG_SEND_DATA_ONLY (error, priv->hook, m); 227 228 if (error) { 229 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 230 return; 231 } 232 } 233 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 234} 235 236/************************************************************************ 237 NETGRAPH NODE STUFF 238 ************************************************************************/ 239 240/* 241 * Constructor for a node 242 */ 243static int 244ng_sppp_constructor (node_p node) 245{ 246 struct sppp *pp; 247 struct ifnet *ifp; 248 priv_p priv; 249 int error = 0; 250 251 /* Allocate node and interface private structures */ 252 MALLOC (priv, priv_p, sizeof(*priv), M_NETGRAPH_SPPP, M_NOWAIT|M_ZERO); 253 if (priv == NULL) 254 return (ENOMEM); 255 256 ifp = if_alloc(IFT_PPP); 257 if (ifp == NULL) { 258 FREE (priv, M_NETGRAPH_SPPP); 259 return (ENOSPC); 260 } 261 pp = IFP2SP(ifp); 262 263 /* Link them together */ 264 ifp->if_softc = priv; 265 priv->ifp = ifp; 266 267 /* Get an interface unit number */ 268 if ((error = ng_sppp_get_unit(&priv->unit)) != 0) { 269 FREE (pp, M_NETGRAPH_SPPP); 270 FREE (priv, M_NETGRAPH_SPPP); 271 return (error); 272 } 273 274 275 /* Link together node and private info */ 276 NG_NODE_SET_PRIVATE (node, priv); 277 priv->node = node; 278 279 /* Initialize interface structure */ 280 if_initname (SP2IFP(pp), NG_SPPP_IFACE_NAME, priv->unit); 281 ifp->if_start = ng_sppp_start; 282 ifp->if_ioctl = ng_sppp_ioctl; 283 ifp->if_watchdog = NULL; 284 ifp->if_flags = (IFF_POINTOPOINT|IFF_MULTICAST); 285 286 /* Give this node the same name as the interface (if possible) */ 287 if (ng_name_node(node, SP2IFP(pp)->if_xname) != 0) 288 log (LOG_WARNING, "%s: can't acquire netgraph name\n", 289 SP2IFP(pp)->if_xname); 290 291 /* Attach the interface */ 292 sppp_attach (ifp); 293 if_attach (ifp); 294 bpfattach (ifp, DLT_NULL, sizeof(u_int32_t)); 295 296 /* Done */ 297 return (0); 298} 299 300/* 301 * Give our ok for a hook to be added 302 */ 303static int 304ng_sppp_newhook (node_p node, hook_p hook, const char *name) 305{ 306 priv_p priv = NG_NODE_PRIVATE (node); 307 308 if (strcmp (name, NG_SPPP_HOOK_DOWNSTREAM) != 0) 309 return (EINVAL); 310 311 if (priv->hook) 312 return (EISCONN); 313 314 priv->hook = hook; 315 NG_HOOK_SET_PRIVATE (hook, priv); 316 317 return (0); 318} 319 320/* 321 * Receive a control message 322 */ 323static int 324ng_sppp_rcvmsg (node_p node, item_p item, hook_p lasthook) 325{ 326 const priv_p priv = NG_NODE_PRIVATE (node); 327 struct ng_mesg *msg = NULL; 328 struct ng_mesg *resp = NULL; 329 struct sppp *const pp = IFP2SP(priv->ifp); 330 int error = 0; 331 332 NGI_GET_MSG (item, msg); 333 switch (msg->header.typecookie) { 334 case NGM_SPPP_COOKIE: 335 switch (msg->header.cmd) { 336 case NGM_SPPP_GET_IFNAME: 337 NG_MKRESPONSE (resp, msg, IFNAMSIZ, M_NOWAIT); 338 if (!resp) { 339 error = ENOMEM; 340 break; 341 } 342 strlcpy(resp->data, SP2IFP(pp)->if_xname, IFNAMSIZ); 343 break; 344 345 default: 346 error = EINVAL; 347 break; 348 } 349 break; 350 default: 351 error = EINVAL; 352 break; 353 } 354 NG_RESPOND_MSG (error, node, item, resp); 355 NG_FREE_MSG (msg); 356 return (error); 357} 358 359/* 360 * Recive data from a hook. Pass the packet to the correct input routine. 361 */ 362static int 363ng_sppp_rcvdata (hook_p hook, item_p item) 364{ 365 struct mbuf *m; 366 const priv_p priv = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 367 struct sppp *const pp = IFP2SP(priv->ifp); 368 369 NGI_GET_M (item, m); 370 NG_FREE_ITEM (item); 371 /* Sanity checks */ 372 KASSERT (m->m_flags & M_PKTHDR, ("%s: not pkthdr", __func__)); 373 if ((SP2IFP(pp)->if_flags & IFF_UP) == 0) { 374 NG_FREE_M (m); 375 return (ENETDOWN); 376 } 377 378 /* Update interface stats */ 379 SP2IFP(pp)->if_ipackets++; 380 381 /* Note receiving interface */ 382 m->m_pkthdr.rcvif = SP2IFP(pp); 383 384 /* Berkeley packet filter */
| 223 len = m->m_pkthdr.len; 224 225 NG_SEND_DATA_ONLY (error, priv->hook, m); 226 227 if (error) { 228 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 229 return; 230 } 231 } 232 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 233} 234 235/************************************************************************ 236 NETGRAPH NODE STUFF 237 ************************************************************************/ 238 239/* 240 * Constructor for a node 241 */ 242static int 243ng_sppp_constructor (node_p node) 244{ 245 struct sppp *pp; 246 struct ifnet *ifp; 247 priv_p priv; 248 int error = 0; 249 250 /* Allocate node and interface private structures */ 251 MALLOC (priv, priv_p, sizeof(*priv), M_NETGRAPH_SPPP, M_NOWAIT|M_ZERO); 252 if (priv == NULL) 253 return (ENOMEM); 254 255 ifp = if_alloc(IFT_PPP); 256 if (ifp == NULL) { 257 FREE (priv, M_NETGRAPH_SPPP); 258 return (ENOSPC); 259 } 260 pp = IFP2SP(ifp); 261 262 /* Link them together */ 263 ifp->if_softc = priv; 264 priv->ifp = ifp; 265 266 /* Get an interface unit number */ 267 if ((error = ng_sppp_get_unit(&priv->unit)) != 0) { 268 FREE (pp, M_NETGRAPH_SPPP); 269 FREE (priv, M_NETGRAPH_SPPP); 270 return (error); 271 } 272 273 274 /* Link together node and private info */ 275 NG_NODE_SET_PRIVATE (node, priv); 276 priv->node = node; 277 278 /* Initialize interface structure */ 279 if_initname (SP2IFP(pp), NG_SPPP_IFACE_NAME, priv->unit); 280 ifp->if_start = ng_sppp_start; 281 ifp->if_ioctl = ng_sppp_ioctl; 282 ifp->if_watchdog = NULL; 283 ifp->if_flags = (IFF_POINTOPOINT|IFF_MULTICAST); 284 285 /* Give this node the same name as the interface (if possible) */ 286 if (ng_name_node(node, SP2IFP(pp)->if_xname) != 0) 287 log (LOG_WARNING, "%s: can't acquire netgraph name\n", 288 SP2IFP(pp)->if_xname); 289 290 /* Attach the interface */ 291 sppp_attach (ifp); 292 if_attach (ifp); 293 bpfattach (ifp, DLT_NULL, sizeof(u_int32_t)); 294 295 /* Done */ 296 return (0); 297} 298 299/* 300 * Give our ok for a hook to be added 301 */ 302static int 303ng_sppp_newhook (node_p node, hook_p hook, const char *name) 304{ 305 priv_p priv = NG_NODE_PRIVATE (node); 306 307 if (strcmp (name, NG_SPPP_HOOK_DOWNSTREAM) != 0) 308 return (EINVAL); 309 310 if (priv->hook) 311 return (EISCONN); 312 313 priv->hook = hook; 314 NG_HOOK_SET_PRIVATE (hook, priv); 315 316 return (0); 317} 318 319/* 320 * Receive a control message 321 */ 322static int 323ng_sppp_rcvmsg (node_p node, item_p item, hook_p lasthook) 324{ 325 const priv_p priv = NG_NODE_PRIVATE (node); 326 struct ng_mesg *msg = NULL; 327 struct ng_mesg *resp = NULL; 328 struct sppp *const pp = IFP2SP(priv->ifp); 329 int error = 0; 330 331 NGI_GET_MSG (item, msg); 332 switch (msg->header.typecookie) { 333 case NGM_SPPP_COOKIE: 334 switch (msg->header.cmd) { 335 case NGM_SPPP_GET_IFNAME: 336 NG_MKRESPONSE (resp, msg, IFNAMSIZ, M_NOWAIT); 337 if (!resp) { 338 error = ENOMEM; 339 break; 340 } 341 strlcpy(resp->data, SP2IFP(pp)->if_xname, IFNAMSIZ); 342 break; 343 344 default: 345 error = EINVAL; 346 break; 347 } 348 break; 349 default: 350 error = EINVAL; 351 break; 352 } 353 NG_RESPOND_MSG (error, node, item, resp); 354 NG_FREE_MSG (msg); 355 return (error); 356} 357 358/* 359 * Recive data from a hook. Pass the packet to the correct input routine. 360 */ 361static int 362ng_sppp_rcvdata (hook_p hook, item_p item) 363{ 364 struct mbuf *m; 365 const priv_p priv = NG_NODE_PRIVATE (NG_HOOK_NODE (hook)); 366 struct sppp *const pp = IFP2SP(priv->ifp); 367 368 NGI_GET_M (item, m); 369 NG_FREE_ITEM (item); 370 /* Sanity checks */ 371 KASSERT (m->m_flags & M_PKTHDR, ("%s: not pkthdr", __func__)); 372 if ((SP2IFP(pp)->if_flags & IFF_UP) == 0) { 373 NG_FREE_M (m); 374 return (ENETDOWN); 375 } 376 377 /* Update interface stats */ 378 SP2IFP(pp)->if_ipackets++; 379 380 /* Note receiving interface */ 381 m->m_pkthdr.rcvif = SP2IFP(pp); 382 383 /* Berkeley packet filter */
|
385 if (SP2IFP(pp)->if_bpf) 386 BPF_MTAP (SP2IFP(pp), m);
| 384 BPF_MTAP (SP2IFP(pp), m);
|
387 388 /* Send packet */ 389 sppp_input (SP2IFP(pp), m); 390 return 0; 391} 392 393/* 394 * Shutdown and remove the node and its associated interface. 395 */ 396static int 397ng_sppp_shutdown (node_p node) 398{ 399 const priv_p priv = NG_NODE_PRIVATE(node); 400 /* Detach from the packet filter list of interfaces. */ 401 bpfdetach (priv->ifp); 402 sppp_detach (priv->ifp); 403 if_detach (priv->ifp); 404 if_free(priv->ifp); 405 ng_sppp_free_unit (priv->unit); 406 FREE (priv, M_NETGRAPH_SPPP); 407 NG_NODE_SET_PRIVATE (node, NULL); 408 NG_NODE_UNREF (node); 409 return (0); 410} 411 412/* 413 * Hook disconnection. 414 */ 415static int 416ng_sppp_disconnect (hook_p hook) 417{ 418 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 419 420 if (priv) 421 priv->hook = NULL; 422 423 return (0); 424}
| 385 386 /* Send packet */ 387 sppp_input (SP2IFP(pp), m); 388 return 0; 389} 390 391/* 392 * Shutdown and remove the node and its associated interface. 393 */ 394static int 395ng_sppp_shutdown (node_p node) 396{ 397 const priv_p priv = NG_NODE_PRIVATE(node); 398 /* Detach from the packet filter list of interfaces. */ 399 bpfdetach (priv->ifp); 400 sppp_detach (priv->ifp); 401 if_detach (priv->ifp); 402 if_free(priv->ifp); 403 ng_sppp_free_unit (priv->unit); 404 FREE (priv, M_NETGRAPH_SPPP); 405 NG_NODE_SET_PRIVATE (node, NULL); 406 NG_NODE_UNREF (node); 407 return (0); 408} 409 410/* 411 * Hook disconnection. 412 */ 413static int 414ng_sppp_disconnect (hook_p hook) 415{ 416 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 417 418 if (priv) 419 priv->hook = NULL; 420 421 return (0); 422}
|