ng_iface.c (647b86df6e2309de7c27fb3414f3daf139616500) | ng_iface.c (15ba31b9ad22b90fbf4849f51de9bf8dcf794264) |
---|---|
1 2/* 3 * ng_iface.c 4 * 5 * Copyright (c) 1996-1999 Whistle Communications, Inc. 6 * All rights reserved. 7 * 8 * Subject to the following obligations and disclaimer of warranty, use and --- 31 unchanged lines hidden (view full) --- 40 * $Whistle: ng_iface.c,v 1.33 1999/11/01 09:24:51 julian Exp $ 41 */ 42 43/* 44 * This node is also a system networking interface. It has 45 * a hook for each protocol (IP, AppleTalk, IPX, etc). Packets 46 * are simply relayed between the interface and the hooks. 47 * | 1 2/* 3 * ng_iface.c 4 * 5 * Copyright (c) 1996-1999 Whistle Communications, Inc. 6 * All rights reserved. 7 * 8 * Subject to the following obligations and disclaimer of warranty, use and --- 31 unchanged lines hidden (view full) --- 40 * $Whistle: ng_iface.c,v 1.33 1999/11/01 09:24:51 julian Exp $ 41 */ 42 43/* 44 * This node is also a system networking interface. It has 45 * a hook for each protocol (IP, AppleTalk, IPX, etc). Packets 46 * are simply relayed between the interface and the hooks. 47 * |
48 * Interfaces are named ng0, ng1, .... FreeBSD does not support 49 * the removal of interfaces, so iface nodes are persistent. | 48 * Interfaces are named ng0, ng1, etc. New nodes take the 49 * first available interface name. |
50 * 51 * This node also includes Berkeley packet filter support. 52 */ 53 | 50 * 51 * This node also includes Berkeley packet filter support. 52 */ 53 |
54#include "opt_inet.h" 55#include "opt_atalk.h" 56#include "opt_ipx.h" 57 | |
58#include <sys/param.h> 59#include <sys/systm.h> 60#include <sys/errno.h> 61#include <sys/kernel.h> 62#include <sys/malloc.h> 63#include <sys/mbuf.h> 64#include <sys/errno.h> 65#include <sys/sockio.h> 66#include <sys/socket.h> 67#include <sys/syslog.h> | 54#include <sys/param.h> 55#include <sys/systm.h> 56#include <sys/errno.h> 57#include <sys/kernel.h> 58#include <sys/malloc.h> 59#include <sys/mbuf.h> 60#include <sys/errno.h> 61#include <sys/sockio.h> 62#include <sys/socket.h> 63#include <sys/syslog.h> |
64#include <sys/libkern.h> |
|
68 69#include <net/if.h> 70#include <net/if_types.h> | 65 66#include <net/if.h> 67#include <net/if_types.h> |
71#include <net/netisr.h> | 68#include <net/intrq.h> 69#include <net/bpf.h> |
72 73#include <netinet/in.h> 74 75#include <netgraph/ng_message.h> 76#include <netgraph/netgraph.h> | 70 71#include <netinet/in.h> 72 73#include <netgraph/ng_message.h> 74#include <netgraph/netgraph.h> |
75#include <netgraph/ng_parse.h> |
|
77#include <netgraph/ng_iface.h> 78#include <netgraph/ng_cisco.h> 79 | 76#include <netgraph/ng_iface.h> 77#include <netgraph/ng_cisco.h> 78 |
80#ifdef INET 81#include <netinet/in_systm.h> 82#include <netinet/in_var.h> 83#include <netinet/in_var.h> 84#endif 85 86#ifdef NETATALK 87#include <netatalk/at.h> 88#include <netatalk/at_var.h> 89#endif 90 91#ifdef IPX 92#include <netipx/ipx.h> 93#include <netipx/ipx_if.h> 94#endif 95 96#ifdef NS 97#include <netns/ns.h> 98#include <netns/ns_if.h> 99#endif 100 101#include <net/bpf.h> 102 | |
103/* This struct describes one address family */ 104struct iffam { | 79/* This struct describes one address family */ 80struct iffam { |
105 char *hookname; /* Name for hook */ 106 u_char af; /* Family number */ 107 u_char netisr; /* or NETISR_NONE */ 108 union { 109 void *_dummy; /* avoid warning */ 110 struct ifqueue *inq; /* if netisr */ 111 void (*input)(struct mbuf *m); /* if direct input */ 112 } u; | 81 sa_family_t family; /* Address family */ 82 const char *hookname; /* Name for hook */ |
113}; 114typedef const struct iffam *iffam_p; 115 | 83}; 84typedef const struct iffam *iffam_p; 85 |
116#define NETISR_NONE 0xff 117 118/* List of address families supported by our interface. Each address 119 family has a way to input packets to it, either by calling a function 120 directly (such as ip_input()) or by adding the packet to a queue and 121 setting a NETISR bit. */ | 86/* List of address families supported by our interface */ |
122const static struct iffam gFamilies[] = { | 87const static struct iffam gFamilies[] = { |
123#ifdef INET 124 { 125 NG_IFACE_HOOK_INET, 126 AF_INET, 127 NETISR_NONE, 128 { ip_input } 129 }, 130#endif 131#ifdef NETATALK 132 { 133 NG_IFACE_HOOK_ATALK, 134 AF_APPLETALK, 135 NETISR_ATALK, 136 { &atintrq2 } 137 }, 138#endif 139#ifdef IPX 140 { 141 NG_IFACE_HOOK_IPX, 142 AF_IPX, 143 NETISR_IPX, 144 { &ipxintrq } 145 }, 146#endif 147#ifdef NS 148 { 149 NG_IFACE_HOOK_NS, 150 AF_NS, 151 NETISR_NS, 152 { &nsintrq } 153 }, 154#endif | 88 { AF_INET, NG_IFACE_HOOK_INET }, 89 { AF_INET6, NG_IFACE_HOOK_INET6 }, 90 { AF_APPLETALK, NG_IFACE_HOOK_ATALK }, 91 { AF_IPX, NG_IFACE_HOOK_IPX }, 92 { AF_ATM, NG_IFACE_HOOK_ATM }, 93 { AF_NATM, NG_IFACE_HOOK_NATM }, 94 { AF_NS, NG_IFACE_HOOK_NS }, |
155}; 156#define NUM_FAMILIES (sizeof(gFamilies) / sizeof(*gFamilies)) 157 158/* Node private data */ 159struct ng_iface_private { | 95}; 96#define NUM_FAMILIES (sizeof(gFamilies) / sizeof(*gFamilies)) 97 98/* Node private data */ 99struct ng_iface_private { |
160 struct ifnet *ifp; /* This interface */ | 100 struct ifnet *ifp; /* Our interface */ 101 int unit; /* Interface unit number */ |
161 node_p node; /* Our netgraph node */ 162 hook_p hooks[NUM_FAMILIES]; /* Hook for each address family */ | 102 node_p node; /* Our netgraph node */ 103 hook_p hooks[NUM_FAMILIES]; /* Hook for each address family */ |
163 struct private *next; /* When hung on the free list */ | |
164}; 165typedef struct ng_iface_private *priv_p; 166 167/* Interface methods */ 168static void ng_iface_start(struct ifnet *ifp); 169static int ng_iface_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 170static int ng_iface_output(struct ifnet *ifp, struct mbuf *m0, | 104}; 105typedef struct ng_iface_private *priv_p; 106 107/* Interface methods */ 108static void ng_iface_start(struct ifnet *ifp); 109static int ng_iface_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 110static int ng_iface_output(struct ifnet *ifp, struct mbuf *m0, |
171 struct sockaddr *dst, struct rtentry *rt0); 172static void ng_iface_bpftap(struct ifnet *ifp, struct mbuf *m, u_int af); | 111 struct sockaddr *dst, struct rtentry *rt0); 112static void ng_iface_bpftap(struct ifnet *ifp, 113 struct mbuf *m, sa_family_t family); |
173#ifdef DEBUG 174static void ng_iface_print_ioctl(struct ifnet *ifp, int cmd, caddr_t data); 175#endif 176 177/* Netgraph methods */ 178static ng_constructor_t ng_iface_constructor; 179static ng_rcvmsg_t ng_iface_rcvmsg; 180static ng_shutdown_t ng_iface_rmnode; 181static ng_newhook_t ng_iface_newhook; 182static ng_rcvdata_t ng_iface_rcvdata; 183static ng_disconnect_t ng_iface_disconnect; 184 185/* Helper stuff */ | 114#ifdef DEBUG 115static void ng_iface_print_ioctl(struct ifnet *ifp, int cmd, caddr_t data); 116#endif 117 118/* Netgraph methods */ 119static ng_constructor_t ng_iface_constructor; 120static ng_rcvmsg_t ng_iface_rcvmsg; 121static ng_shutdown_t ng_iface_rmnode; 122static ng_newhook_t ng_iface_newhook; 123static ng_rcvdata_t ng_iface_rcvdata; 124static ng_disconnect_t ng_iface_disconnect; 125 126/* Helper stuff */ |
186static iffam_p get_iffam_from_af(int af); | 127static iffam_p get_iffam_from_af(sa_family_t family); |
187static iffam_p get_iffam_from_hook(priv_p priv, hook_p hook); 188static iffam_p get_iffam_from_name(const char *name); 189static hook_p *get_hook_from_iffam(priv_p priv, iffam_p iffam); 190 | 128static iffam_p get_iffam_from_hook(priv_p priv, hook_p hook); 129static iffam_p get_iffam_from_name(const char *name); 130static hook_p *get_hook_from_iffam(priv_p priv, iffam_p iffam); 131 |
132/* Parse type for struct ng_iface_ifname */ 133static const struct ng_parse_fixedstring_info ng_iface_ifname_info = { 134 NG_IFACE_IFACE_NAME_MAX + 1 135}; 136static const struct ng_parse_type ng_iface_ifname_type = { 137 &ng_parse_fixedstring_type, 138 &ng_iface_ifname_info 139}; 140 141/* Parse type for struct ng_cisco_ipaddr */ 142static const struct ng_parse_struct_info 143 ng_cisco_ipaddr_type_info = NG_CISCO_IPADDR_TYPE_INFO; 144static const struct ng_parse_type ng_cisco_ipaddr_type = { 145 &ng_parse_struct_type, 146 &ng_cisco_ipaddr_type_info 147}; 148 149/* List of commands and how to convert arguments to/from ASCII */ 150static const struct ng_cmdlist ng_iface_cmds[] = { 151 { 152 NGM_IFACE_COOKIE, 153 NGM_IFACE_GET_IFNAME, 154 "getifname", 155 NULL, 156 &ng_iface_ifname_type 157 }, 158 { 159 NGM_IFACE_COOKIE, 160 NGM_IFACE_POINT2POINT, 161 "point2point", 162 NULL, 163 NULL 164 }, 165 { 166 NGM_IFACE_COOKIE, 167 NGM_IFACE_BROADCAST, 168 "broadcast", 169 NULL, 170 NULL 171 }, 172 { 173 NGM_CISCO_COOKIE, 174 NGM_CISCO_GET_IPADDR, 175 "getipaddr", 176 NULL, 177 &ng_cisco_ipaddr_type 178 }, 179 { 0 } 180}; 181 |
|
191/* Node type descriptor */ 192static struct ng_type typestruct = { 193 NG_VERSION, 194 NG_IFACE_NODE_TYPE, 195 NULL, 196 ng_iface_constructor, 197 ng_iface_rcvmsg, 198 ng_iface_rmnode, 199 ng_iface_newhook, 200 NULL, 201 NULL, 202 ng_iface_rcvdata, 203 ng_iface_rcvdata, 204 ng_iface_disconnect, | 182/* Node type descriptor */ 183static struct ng_type typestruct = { 184 NG_VERSION, 185 NG_IFACE_NODE_TYPE, 186 NULL, 187 ng_iface_constructor, 188 ng_iface_rcvmsg, 189 ng_iface_rmnode, 190 ng_iface_newhook, 191 NULL, 192 NULL, 193 ng_iface_rcvdata, 194 ng_iface_rcvdata, 195 ng_iface_disconnect, |
205 NULL | 196 ng_iface_cmds |
206}; 207NETGRAPH_INIT(iface, &typestruct); 208 | 197}; 198NETGRAPH_INIT(iface, &typestruct); 199 |
209static char ng_iface_ifname[] = NG_IFACE_IFACE_NAME; 210static int ng_iface_next_unit; | 200/* We keep a bitmap indicating which unit numbers are free. 201 One means the unit number is free, zero means it's taken. */ 202static int *ng_iface_units = NULL; 203static int ng_iface_units_len = 0; |
211 | 204 |
205#define UNITS_BITSPERWORD (sizeof(*ng_iface_units) * NBBY) 206 |
|
212/************************************************************************ 213 HELPER STUFF 214 ************************************************************************/ 215 216/* 217 * Get the family descriptor from the family ID 218 */ 219static __inline__ iffam_p | 207/************************************************************************ 208 HELPER STUFF 209 ************************************************************************/ 210 211/* 212 * Get the family descriptor from the family ID 213 */ 214static __inline__ iffam_p |
220get_iffam_from_af(int af) | 215get_iffam_from_af(sa_family_t family) |
221{ 222 iffam_p iffam; 223 int k; 224 225 for (k = 0; k < NUM_FAMILIES; k++) { 226 iffam = &gFamilies[k]; | 216{ 217 iffam_p iffam; 218 int k; 219 220 for (k = 0; k < NUM_FAMILIES; k++) { 221 iffam = &gFamilies[k]; |
227 if (iffam->af == af) | 222 if (iffam->family == family) |
228 return (iffam); 229 } 230 return (NULL); 231} 232 233/* 234 * Get the family descriptor from the hook 235 */ --- 30 unchanged lines hidden (view full) --- 266 for (k = 0; k < NUM_FAMILIES; k++) { 267 iffam = &gFamilies[k]; 268 if (!strcmp(iffam->hookname, name)) 269 return (iffam); 270 } 271 return (NULL); 272} 273 | 223 return (iffam); 224 } 225 return (NULL); 226} 227 228/* 229 * Get the family descriptor from the hook 230 */ --- 30 unchanged lines hidden (view full) --- 261 for (k = 0; k < NUM_FAMILIES; k++) { 262 iffam = &gFamilies[k]; 263 if (!strcmp(iffam->hookname, name)) 264 return (iffam); 265 } 266 return (NULL); 267} 268 |
269/* 270 * Find the first free unit number for a new interface. 271 * Increase the size of the unit bitmap as necessary. 272 */ 273static __inline__ int 274ng_iface_get_unit(int *unit) 275{ 276 int index, bit; 277 278 for (index = 0; index < ng_iface_units_len 279 && ng_iface_units[index] == 0; index++); 280 if (index == ng_iface_units_len) { /* extend array */ 281 int i, *newarray, newlen; 282 283 newlen = (2 * ng_iface_units_len) + 4; 284 MALLOC(newarray, int *, newlen * sizeof(*ng_iface_units), 285 M_NETGRAPH, M_WAITOK); 286 if (newarray == NULL) 287 return (ENOMEM); 288 bcopy(ng_iface_units, newarray, 289 ng_iface_units_len * sizeof(*ng_iface_units)); 290 for (i = ng_iface_units_len; i < newlen; i++) 291 newarray[i] = ~0; 292 if (ng_iface_units != NULL) 293 FREE(ng_iface_units, M_NETGRAPH); 294 ng_iface_units = newarray; 295 ng_iface_units_len = newlen; 296 } 297 bit = ffs(ng_iface_units[index]) - 1; 298 KASSERT(bit >= 0 && bit <= UNITS_BITSPERWORD - 1, 299 ("%s: word=%d bit=%d", __FUNCTION__, ng_iface_units[index], bit)); 300 ng_iface_units[index] &= ~(1 << bit); 301 *unit = (index * UNITS_BITSPERWORD) + bit; 302 return (0); 303} 304 305/* 306 * Free a no longer needed unit number. 307 */ 308static __inline__ void 309ng_iface_free_unit(int unit) 310{ 311 int index, bit; 312 313 index = unit / UNITS_BITSPERWORD; 314 bit = unit % UNITS_BITSPERWORD; 315 KASSERT(index < ng_iface_units_len, 316 ("%s: unit=%d len=%d", __FUNCTION__, unit, ng_iface_units_len)); 317 KASSERT((ng_iface_units[index] & (1 << bit)) == 0, 318 ("%s: unit=%d is free", __FUNCTION__, unit)); 319 ng_iface_units[index] |= (1 << bit); 320 /* 321 * XXX We could think about reducing the size of ng_iface_units[] 322 * XXX here if the last portion is all ones 323 */ 324} 325 |
|
274/************************************************************************ 275 INTERFACE STUFF 276 ************************************************************************/ 277 278/* 279 * Process an ioctl for the virtual interface 280 */ 281static int --- 75 unchanged lines hidden (view full) --- 357 int len, error = 0; 358 359 /* Check interface flags */ 360 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 361 m_freem(m); 362 return (ENETDOWN); 363 } 364 | 326/************************************************************************ 327 INTERFACE STUFF 328 ************************************************************************/ 329 330/* 331 * Process an ioctl for the virtual interface 332 */ 333static int --- 75 unchanged lines hidden (view full) --- 409 int len, error = 0; 410 411 /* Check interface flags */ 412 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 413 m_freem(m); 414 return (ENETDOWN); 415 } 416 |
417 /* BPF writes need to be handled specially */ 418 if (dst->sa_family == AF_UNSPEC) { 419 if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) 420 return (ENOBUFS); 421 dst->sa_family = (sa_family_t)*mtod(m, int32_t *); 422 m->m_data += 4; 423 m->m_len -= 4; 424 m->m_pkthdr.len -= 4; 425 } 426 |
|
365 /* Berkeley packet filter */ 366 ng_iface_bpftap(ifp, m, dst->sa_family); 367 368 /* Check address family to determine hook (if known) */ 369 if (iffam == NULL) { 370 m_freem(m); 371 log(LOG_WARNING, "%s%d: can't handle af%d\n", | 427 /* Berkeley packet filter */ 428 ng_iface_bpftap(ifp, m, dst->sa_family); 429 430 /* Check address family to determine hook (if known) */ 431 if (iffam == NULL) { 432 m_freem(m); 433 log(LOG_WARNING, "%s%d: can't handle af%d\n", |
372 ifp->if_name, ifp->if_unit, dst->sa_family); | 434 ifp->if_name, ifp->if_unit, (int)dst->sa_family); |
373 return (EAFNOSUPPORT); 374 } 375 376 /* Copy length before the mbuf gets invalidated */ 377 len = m->m_pkthdr.len; 378 379 /* Send packet; if hook is not connected, mbuf will get freed. */ 380 NG_SEND_DATA(error, *get_hook_from_iffam(priv, iffam), m, meta); --- 16 unchanged lines hidden (view full) --- 397 printf("%s%d: %s called?", ifp->if_name, ifp->if_unit, __FUNCTION__); 398} 399 400/* 401 * Flash a packet by the BPF (requires prepending 4 byte AF header) 402 * Note the phoney mbuf; this is OK because BPF treats it read-only. 403 */ 404static void | 435 return (EAFNOSUPPORT); 436 } 437 438 /* Copy length before the mbuf gets invalidated */ 439 len = m->m_pkthdr.len; 440 441 /* Send packet; if hook is not connected, mbuf will get freed. */ 442 NG_SEND_DATA(error, *get_hook_from_iffam(priv, iffam), m, meta); --- 16 unchanged lines hidden (view full) --- 459 printf("%s%d: %s called?", ifp->if_name, ifp->if_unit, __FUNCTION__); 460} 461 462/* 463 * Flash a packet by the BPF (requires prepending 4 byte AF header) 464 * Note the phoney mbuf; this is OK because BPF treats it read-only. 465 */ 466static void |
405ng_iface_bpftap(struct ifnet *ifp, struct mbuf *m, u_int af) | 467ng_iface_bpftap(struct ifnet *ifp, struct mbuf *m, sa_family_t family) |
406{ | 468{ |
407 struct mbuf m2; | 469 int32_t family4 = (int32_t)family; 470 struct mbuf m0; |
408 | 471 |
409 if (ifp->if_bpf) { 410 if (af == AF_UNSPEC) { 411 af = *(mtod(m, int *)); 412 m->m_len -= sizeof(int); 413 m->m_pkthdr.len -= sizeof(int); 414 m->m_data += sizeof(int); 415 } 416 if (!ifp->if_bpf) 417 return; 418 m2.m_next = m; 419 m2.m_len = 4; 420 m2.m_data = (char *) ⁡ 421 bpf_mtap(ifp, &m2); | 472 KASSERT(family != AF_UNSPEC, ("%s: family=AF_UNSPEC", __FUNCTION__)); 473 if (ifp->if_bpf != NULL) { 474 bzero(&m0, sizeof(m0)); 475 m0.m_next = m; 476 m0.m_len = sizeof(family4); 477 m0.m_data = (char *)&family4; 478 bpf_mtap(ifp, &m0); |
422 } 423} 424 425#ifdef DEBUG 426/* 427 * Display an ioctl to the virtual interface 428 */ 429 --- 54 unchanged lines hidden (view full) --- 484 return (ENOMEM); 485 } 486 bzero(ifp, sizeof(*ifp)); 487 488 /* Link them together */ 489 ifp->if_softc = priv; 490 priv->ifp = ifp; 491 | 479 } 480} 481 482#ifdef DEBUG 483/* 484 * Display an ioctl to the virtual interface 485 */ 486 --- 54 unchanged lines hidden (view full) --- 541 return (ENOMEM); 542 } 543 bzero(ifp, sizeof(*ifp)); 544 545 /* Link them together */ 546 ifp->if_softc = priv; 547 priv->ifp = ifp; 548 |
492 /* Call generic node constructor */ 493 if ((error = ng_make_node_common(&typestruct, nodep))) { | 549 /* Get an interface unit number */ 550 if ((error = ng_iface_get_unit(&priv->unit)) != 0) { 551 FREE(ifp, M_NETGRAPH); |
494 FREE(priv, M_NETGRAPH); | 552 FREE(priv, M_NETGRAPH); |
553 return (error); 554 } 555 556 /* Call generic node constructor */ 557 if ((error = ng_make_node_common(&typestruct, nodep)) != 0) { 558 ng_iface_free_unit(priv->unit); |
|
495 FREE(ifp, M_NETGRAPH); | 559 FREE(ifp, M_NETGRAPH); |
560 FREE(priv, M_NETGRAPH); |
|
496 return (error); 497 } 498 node = *nodep; 499 500 /* Link together node and private info */ 501 node->private = priv; 502 priv->node = node; 503 504 /* Initialize interface structure */ | 561 return (error); 562 } 563 node = *nodep; 564 565 /* Link together node and private info */ 566 node->private = priv; 567 priv->node = node; 568 569 /* Initialize interface structure */ |
505 ifp->if_name = ng_iface_ifname; 506 ifp->if_unit = ng_iface_next_unit++; | 570 ifp->if_name = NG_IFACE_IFACE_NAME; 571 ifp->if_unit = priv->unit; |
507 ifp->if_output = ng_iface_output; 508 ifp->if_start = ng_iface_start; 509 ifp->if_ioctl = ng_iface_ioctl; 510 ifp->if_watchdog = NULL; 511 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 512 ifp->if_mtu = NG_IFACE_MTU_DEFAULT; | 572 ifp->if_output = ng_iface_output; 573 ifp->if_start = ng_iface_start; 574 ifp->if_ioctl = ng_iface_ioctl; 575 ifp->if_watchdog = NULL; 576 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 577 ifp->if_mtu = NG_IFACE_MTU_DEFAULT; |
513 ifp->if_flags = (IFF_SIMPLEX | IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST); | 578 ifp->if_flags = (IFF_SIMPLEX|IFF_POINTOPOINT|IFF_NOARP|IFF_MULTICAST); |
514 ifp->if_type = IFT_PROPVIRTUAL; /* XXX */ 515 ifp->if_addrlen = 0; /* XXX */ 516 ifp->if_hdrlen = 0; /* XXX */ 517 ifp->if_baudrate = 64000; /* XXX */ 518 TAILQ_INIT(&ifp->if_addrhead); 519 520 /* Give this node the same name as the interface (if possible) */ 521 bzero(ifname, sizeof(ifname)); | 579 ifp->if_type = IFT_PROPVIRTUAL; /* XXX */ 580 ifp->if_addrlen = 0; /* XXX */ 581 ifp->if_hdrlen = 0; /* XXX */ 582 ifp->if_baudrate = 64000; /* XXX */ 583 TAILQ_INIT(&ifp->if_addrhead); 584 585 /* Give this node the same name as the interface (if possible) */ 586 bzero(ifname, sizeof(ifname)); |
522 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); 523 (void) ng_name_node(node, ifname); | 587 snprintf(ifname, sizeof(ifname), "%s%d", ifp->if_name, ifp->if_unit); 588 if (ng_name_node(node, ifname) != 0) 589 log(LOG_WARNING, "%s: can't acquire netgraph name\n", ifname); |
524 525 /* Attach the interface */ 526 if_attach(ifp); 527 bpfattach(ifp, DLT_NULL, sizeof(u_int)); 528 529 /* Done */ 530 return (0); 531} --- 35 unchanged lines hidden (view full) --- 567 { 568 struct ng_iface_ifname *arg; 569 570 NG_MKRESPONSE(resp, msg, sizeof(*arg), M_NOWAIT); 571 if (resp == NULL) { 572 error = ENOMEM; 573 break; 574 } | 590 591 /* Attach the interface */ 592 if_attach(ifp); 593 bpfattach(ifp, DLT_NULL, sizeof(u_int)); 594 595 /* Done */ 596 return (0); 597} --- 35 unchanged lines hidden (view full) --- 633 { 634 struct ng_iface_ifname *arg; 635 636 NG_MKRESPONSE(resp, msg, sizeof(*arg), M_NOWAIT); 637 if (resp == NULL) { 638 error = ENOMEM; 639 break; 640 } |
575 arg = (struct ng_iface_ifname *) resp->data; 576 sprintf(arg->ngif_name, | 641 arg = (struct ng_iface_ifname *)resp->data; 642 snprintf(arg->ngif_name, sizeof(arg->ngif_name), |
577 "%s%d", ifp->if_name, ifp->if_unit); 578 break; 579 } 580 | 643 "%s%d", ifp->if_name, ifp->if_unit); 644 break; 645 } 646 |
581 case NGM_IFACE_GET_IFADDRS: | 647 case NGM_IFACE_POINT2POINT: 648 case NGM_IFACE_BROADCAST: |
582 { | 649 { |
583 struct ifaddr *ifa; 584 caddr_t ptr; 585 int buflen; | |
586 | 650 |
587#define SA_SIZE(s) ((s)->sa_len<sizeof(*(s))? sizeof(*(s)):(s)->sa_len) | 651 /* Deny request if interface is UP */ 652 if ((ifp->if_flags & IFF_UP) != 0) 653 return (EBUSY); |
588 | 654 |
589 /* Determine size of response and allocate it */ 590 buflen = 0; 591 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 592 buflen += SA_SIZE(ifa->ifa_addr); 593 NG_MKRESPONSE(resp, msg, buflen, M_NOWAIT); 594 if (resp == NULL) { 595 error = ENOMEM; | 655 /* Change flags */ 656 switch (msg->header.cmd) { 657 case NGM_IFACE_POINT2POINT: 658 ifp->if_flags |= IFF_POINTOPOINT; 659 ifp->if_flags &= ~IFF_BROADCAST; |
596 break; | 660 break; |
661 case NGM_IFACE_BROADCAST: 662 ifp->if_flags &= ~IFF_POINTOPOINT; 663 ifp->if_flags |= IFF_BROADCAST; 664 break; |
|
597 } | 665 } |
598 599 /* Add addresses */ 600 ptr = resp->data; 601 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 602 const int len = SA_SIZE(ifa->ifa_addr); 603 604 if (buflen < len) { 605 log(LOG_ERR, "%s%d: len changed?\n", 606 ifp->if_name, ifp->if_unit); 607 break; 608 } 609 bcopy(ifa->ifa_addr, ptr, len); 610 ptr += len; 611 buflen -= len; 612 } | |
613 break; | 666 break; |
614#undef SA_SIZE | |
615 } 616 617 default: 618 error = EINVAL; 619 break; 620 } 621 break; 622 case NGM_CISCO_COOKIE: 623 switch (msg->header.cmd) { 624 case NGM_CISCO_GET_IPADDR: /* we understand this too */ 625 { 626 struct ifaddr *ifa; 627 628 /* Return the first configured IP address */ 629 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | 667 } 668 669 default: 670 error = EINVAL; 671 break; 672 } 673 break; 674 case NGM_CISCO_COOKIE: 675 switch (msg->header.cmd) { 676 case NGM_CISCO_GET_IPADDR: /* we understand this too */ 677 { 678 struct ifaddr *ifa; 679 680 /* Return the first configured IP address */ 681 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { |
630 struct in_addr *ips; | 682 struct ng_cisco_ipaddr *ips; |
631 632 if (ifa->ifa_addr->sa_family != AF_INET) 633 continue; | 683 684 if (ifa->ifa_addr->sa_family != AF_INET) 685 continue; |
634 NG_MKRESPONSE(resp, msg, 635 2 * sizeof(*ips), M_NOWAIT); | 686 NG_MKRESPONSE(resp, msg, sizeof(ips), M_NOWAIT); |
636 if (resp == NULL) { 637 error = ENOMEM; 638 break; 639 } | 687 if (resp == NULL) { 688 error = ENOMEM; 689 break; 690 } |
640 ips = (struct in_addr *) resp->data; 641 ips[0] = ((struct sockaddr_in *) | 691 ips = (struct ng_cisco_ipaddr *)resp->data; 692 ips->ipaddr = ((struct sockaddr_in *) |
642 ifa->ifa_addr)->sin_addr; | 693 ifa->ifa_addr)->sin_addr; |
643 ips[1] = ((struct sockaddr_in *) | 694 ips->netmask = ((struct sockaddr_in *) |
644 ifa->ifa_netmask)->sin_addr; 645 break; 646 } 647 648 /* No IP addresses on this interface? */ 649 if (ifa == NULL) 650 error = EADDRNOTAVAIL; 651 break; --- 19 unchanged lines hidden (view full) --- 671 * Recive data from a hook. Pass the packet to the correct input routine. 672 */ 673static int 674ng_iface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta) 675{ 676 const priv_p priv = hook->node->private; 677 const iffam_p iffam = get_iffam_from_hook(priv, hook); 678 struct ifnet *const ifp = priv->ifp; | 695 ifa->ifa_netmask)->sin_addr; 696 break; 697 } 698 699 /* No IP addresses on this interface? */ 700 if (ifa == NULL) 701 error = EADDRNOTAVAIL; 702 break; --- 19 unchanged lines hidden (view full) --- 722 * Recive data from a hook. Pass the packet to the correct input routine. 723 */ 724static int 725ng_iface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta) 726{ 727 const priv_p priv = hook->node->private; 728 const iffam_p iffam = get_iffam_from_hook(priv, hook); 729 struct ifnet *const ifp = priv->ifp; |
679 int s, error = 0; | |
680 681 /* Sanity checks */ 682 KASSERT(iffam != NULL, ("%s: iffam", __FUNCTION__)); 683 KASSERT(m->m_flags & M_PKTHDR, ("%s: not pkthdr", __FUNCTION__)); 684 if (m == NULL) 685 return (EINVAL); 686 if ((ifp->if_flags & IFF_UP) == 0) { 687 NG_FREE_DATA(m, meta); 688 return (ENETDOWN); 689 } 690 691 /* Update interface stats */ 692 ifp->if_ipackets++; 693 ifp->if_ibytes += m->m_pkthdr.len; 694 695 /* Note receiving interface */ 696 m->m_pkthdr.rcvif = ifp; 697 698 /* Berkeley packet filter */ | 730 731 /* Sanity checks */ 732 KASSERT(iffam != NULL, ("%s: iffam", __FUNCTION__)); 733 KASSERT(m->m_flags & M_PKTHDR, ("%s: not pkthdr", __FUNCTION__)); 734 if (m == NULL) 735 return (EINVAL); 736 if ((ifp->if_flags & IFF_UP) == 0) { 737 NG_FREE_DATA(m, meta); 738 return (ENETDOWN); 739 } 740 741 /* Update interface stats */ 742 ifp->if_ipackets++; 743 ifp->if_ibytes += m->m_pkthdr.len; 744 745 /* Note receiving interface */ 746 m->m_pkthdr.rcvif = ifp; 747 748 /* Berkeley packet filter */ |
699 ng_iface_bpftap(ifp, m, iffam->af); | 749 ng_iface_bpftap(ifp, m, iffam->family); |
700 701 /* Ignore any meta-data */ 702 NG_FREE_META(meta); 703 | 750 751 /* Ignore any meta-data */ 752 NG_FREE_META(meta); 753 |
704 /* Send packet, either by NETISR or use a direct input function */ 705 switch (iffam->netisr) { 706 case NETISR_NONE: 707 (*iffam->u.input)(m); 708 break; 709 default: 710 s = splimp(); 711 schednetisr(iffam->netisr); 712 if (IF_QFULL(iffam->u.inq)) { 713 IF_DROP(iffam->u.inq); 714 m_freem(m); 715 error = ENOBUFS; 716 } else 717 IF_ENQUEUE(iffam->u.inq, m); 718 splx(s); 719 break; 720 } 721 722 /* Done */ 723 return (error); | 754 /* Send packet */ 755 return family_enqueue(iffam->family, m); |
724} 725 726/* | 756} 757 758/* |
727 * Because the BSD networking code doesn't support the removal of 728 * networking interfaces, iface nodes (once created) are persistent. 729 * So this method breaks all connections and marks the interface 730 * down, but does not remove the node. | 759 * Shutdown and remove the node and its associated interface. |
731 */ 732static int 733ng_iface_rmnode(node_p node) 734{ 735 const priv_p priv = node->private; | 760 */ 761static int 762ng_iface_rmnode(node_p node) 763{ 764 const priv_p priv = node->private; |
736 struct ifnet *const ifp = priv->ifp; | |
737 738 ng_cutlinks(node); | 765 766 ng_cutlinks(node); |
739 node->flags &= ~NG_INVALID; 740 ifp->if_flags &= ~(IFF_UP | IFF_RUNNING | IFF_OACTIVE); | 767 ng_unname(node); 768 if_detach(priv->ifp); 769 priv->ifp = NULL; 770 ng_iface_free_unit(priv->unit); 771 FREE(priv, M_NETGRAPH); 772 node->private = NULL; 773 ng_unref(node); |
741 return (0); 742} 743 744/* | 774 return (0); 775} 776 777/* |
745 * Hook disconnection | 778 * Hook disconnection. Note that we do *not* shutdown when all 779 * hooks have been disconnected. |
746 */ 747static int 748ng_iface_disconnect(hook_p hook) 749{ 750 const priv_p priv = hook->node->private; 751 const iffam_p iffam = get_iffam_from_hook(priv, hook); 752 753 if (iffam == NULL) 754 panic(__FUNCTION__); 755 *get_hook_from_iffam(priv, iffam) = NULL; 756 return (0); 757} 758 | 780 */ 781static int 782ng_iface_disconnect(hook_p hook) 783{ 784 const priv_p priv = hook->node->private; 785 const iffam_p iffam = get_iffam_from_hook(priv, hook); 786 787 if (iffam == NULL) 788 panic(__FUNCTION__); 789 *get_hook_from_iffam(priv, iffam) = NULL; 790 return (0); 791} 792 |