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 *) &af;
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