if_ethersubr.c (5c9ef378541ddaf6c7606a454ba992c610c09dd0) if_ethersubr.c (833e8dc5ab711a9485790d950801e32798d55558)
1/*-
2 * Copyright (c) 1982, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 64 unchanged lines hidden (view full) ---

73#include <netinet/if_ether.h>
74#include <netinet/in_rss.h>
75#include <netinet/ip_carp.h>
76#include <netinet/ip_var.h>
77#endif
78#ifdef INET6
79#include <netinet6/nd6.h>
80#endif
1/*-
2 * Copyright (c) 1982, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 64 unchanged lines hidden (view full) ---

73#include <netinet/if_ether.h>
74#include <netinet/in_rss.h>
75#include <netinet/ip_carp.h>
76#include <netinet/ip_var.h>
77#endif
78#ifdef INET6
79#include <netinet6/nd6.h>
80#endif
81#include <net/rt_nhops.h>
82
83int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m);
84int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp,
85 const struct sockaddr *dst, short *tp, int *hlen);
86
87#include <security/mac/mac_framework.h>
88
89#ifdef CTASSERT

--- 25 unchanged lines hidden (view full) ---

115 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
116
117static int ether_resolvemulti(struct ifnet *, struct sockaddr **,
118 struct sockaddr *);
119#ifdef VIMAGE
120static void ether_reassign(struct ifnet *, struct vnet *, char *);
121#endif
122
81
82int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m);
83int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp,
84 const struct sockaddr *dst, short *tp, int *hlen);
85
86#include <security/mac/mac_framework.h>
87
88#ifdef CTASSERT

--- 25 unchanged lines hidden (view full) ---

114 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
115
116static int ether_resolvemulti(struct ifnet *, struct sockaddr **,
117 struct sockaddr *);
118#ifdef VIMAGE
119static void ether_reassign(struct ifnet *, struct vnet *, char *);
120#endif
121
123int ether_output_full(struct ifnet *ifp, struct mbuf *m,
124 const struct sockaddr *dst, struct route *ro);
125int ether_output2(struct ifnet *ifp, struct mbuf *m, struct nhop_prepend *nh,
126 int af);
127
128static int loopback_frame(struct ifnet *ifp, struct mbuf *m, int family,
129 int hlen);
130
131/* XXX: should be in an arp support file, not here */
132static MALLOC_DEFINE(M_ARPCOM, "arpcom", "802.* interface internals");
133
134#define ETHER_IS_BROADCAST(addr) \
135 (bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0)
136
137#define senderr(e) do { error = (e); goto bad;} while (0)
138
139static void
140update_mbuf_csumflags(struct mbuf *src, struct mbuf *dst)
141{

--- 5 unchanged lines hidden (view full) ---

147 csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
148 if (src->m_pkthdr.csum_flags & CSUM_SCTP)
149 csum_flags |= CSUM_SCTP_VALID;
150 dst->m_pkthdr.csum_flags |= csum_flags;
151 if (csum_flags & CSUM_DATA_VALID)
152 dst->m_pkthdr.csum_data = 0xffff;
153}
154
122#define ETHER_IS_BROADCAST(addr) \
123 (bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0)
124
125#define senderr(e) do { error = (e); goto bad;} while (0)
126
127static void
128update_mbuf_csumflags(struct mbuf *src, struct mbuf *dst)
129{

--- 5 unchanged lines hidden (view full) ---

135 csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
136 if (src->m_pkthdr.csum_flags & CSUM_SCTP)
137 csum_flags |= CSUM_SCTP_VALID;
138 dst->m_pkthdr.csum_flags |= csum_flags;
139 if (csum_flags & CSUM_DATA_VALID)
140 dst->m_pkthdr.csum_data = 0xffff;
141}
142
155int
156ether_output(struct ifnet *ifp, struct mbuf *m,
157 const struct sockaddr *dst, struct route *ro)
158{
159 if (ro != NULL && (ro->ro_flags & RT_NHOP))
160 return (ether_output2(ifp, m, (struct nhop_prepend *)ro->ro_lle,
161 (ro->ro_flags >> 8) & 0xFF));
162
163 return (ether_output_full(ifp, m, dst, ro));
164}
165
166/*
167 * Ethernet output routine.
168 * Encapsulate a packet of type family for the local net.
169 * Use trailer local net encapsulation if enough data in first
170 * packet leaves a multiple of 512 bytes of data in remainder.
171 */
172int
143/*
144 * Ethernet output routine.
145 * Encapsulate a packet of type family for the local net.
146 * Use trailer local net encapsulation if enough data in first
147 * packet leaves a multiple of 512 bytes of data in remainder.
148 */
149int
173ether_output_full(struct ifnet *ifp, struct mbuf *m,
150ether_output(struct ifnet *ifp, struct mbuf *m,
174 const struct sockaddr *dst, struct route *ro)
175{
176 short type;
177 int error = 0, hdrcmplt = 0;
178 u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN];
179 struct llentry *lle = NULL;
180 struct rtentry *rt0 = NULL;
181 struct ether_header *eh;

--- 120 unchanged lines hidden (view full) ---

302 * XXX To make a simplex device behave exactly like a duplex
303 * device, we should copy in the case of sending to our own
304 * ethernet address (thus letting the original actually appear
305 * on the wire). However, we don't do that here for security
306 * reasons and compatibility with the original behavior.
307 */
308 if ((ifp->if_flags & IFF_SIMPLEX) && loop_copy &&
309 ((t = pf_find_mtag(m)) == NULL || !t->routed)) {
151 const struct sockaddr *dst, struct route *ro)
152{
153 short type;
154 int error = 0, hdrcmplt = 0;
155 u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN];
156 struct llentry *lle = NULL;
157 struct rtentry *rt0 = NULL;
158 struct ether_header *eh;

--- 120 unchanged lines hidden (view full) ---

279 * XXX To make a simplex device behave exactly like a duplex
280 * device, we should copy in the case of sending to our own
281 * ethernet address (thus letting the original actually appear
282 * on the wire). However, we don't do that here for security
283 * reasons and compatibility with the original behavior.
284 */
285 if ((ifp->if_flags & IFF_SIMPLEX) && loop_copy &&
286 ((t = pf_find_mtag(m)) == NULL || !t->routed)) {
310 if ((m->m_flags & M_BCAST) || (bcmp(eh->ether_dhost,
311 eh->ether_shost, ETHER_ADDR_LEN) == 0)) {
312 /* Either broadcast or to-us L2 header */
313 if (loopback_frame(ifp, m, dst->sa_family, hlen) == 1)
314 return (0);
287 if (m->m_flags & M_BCAST) {
288 struct mbuf *n;
289
290 /*
291 * Because if_simloop() modifies the packet, we need a
292 * writable copy through m_dup() instead of a readonly
293 * one as m_copy[m] would give us. The alternative would
294 * be to modify if_simloop() to handle the readonly mbuf,
295 * but performancewise it is mostly equivalent (trading
296 * extra data copying vs. extra locking).
297 *
298 * XXX This is a local workaround. A number of less
299 * often used kernel parts suffer from the same bug.
300 * See PR kern/105943 for a proposed general solution.
301 */
302 if ((n = m_dup(m, M_NOWAIT)) != NULL) {
303 update_mbuf_csumflags(m, n);
304 (void)if_simloop(ifp, n, dst->sa_family, hlen);
305 } else
306 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
307 } else if (bcmp(eh->ether_dhost, eh->ether_shost,
308 ETHER_ADDR_LEN) == 0) {
309 update_mbuf_csumflags(m, m);
310 (void) if_simloop(ifp, m, dst->sa_family, hlen);
311 return (0); /* XXX */
315 }
316 }
317
318 /*
319 * Bridges require special output handling.
320 */
321 if (ifp->if_bridge) {
322 BRIDGE_OUTPUT(ifp, m, error);
323 return (error);
324 }
325
326#if defined(INET) || defined(INET6)
327 if (ifp->if_carp &&
328 (error = (*carp_output_p)(ifp, m, dst)))
329 goto bad;
330#endif
331
332 /* Handle ng_ether(4) processing, if any */
312 }
313 }
314
315 /*
316 * Bridges require special output handling.
317 */
318 if (ifp->if_bridge) {
319 BRIDGE_OUTPUT(ifp, m, error);
320 return (error);
321 }
322
323#if defined(INET) || defined(INET6)
324 if (ifp->if_carp &&
325 (error = (*carp_output_p)(ifp, m, dst)))
326 goto bad;
327#endif
328
329 /* Handle ng_ether(4) processing, if any */
333 if (IFP2AC(ifp)->ac_netgraph != NULL) {
330 if (ifp->if_l2com != NULL) {
334 KASSERT(ng_ether_output_p != NULL,
335 ("ng_ether_output_p is NULL"));
336 if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) {
337bad: if (m != NULL)
338 m_freem(m);
339 return (error);
340 }
341 if (m == NULL)
342 return (0);
343 }
344
345 /* Continue with link-layer output */
346 return ether_output_frame(ifp, m);
347}
348
349/*
331 KASSERT(ng_ether_output_p != NULL,
332 ("ng_ether_output_p is NULL"));
333 if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) {
334bad: if (m != NULL)
335 m_freem(m);
336 return (error);
337 }
338 if (m == NULL)
339 return (0);
340 }
341
342 /* Continue with link-layer output */
343 return ether_output_frame(ifp, m);
344}
345
346/*
350 * We assume this function to be called for
351 * ip[6]_output(), with already pre-compiled L2 header.
352 *
353 * Function assumes all loopback routing is already done on L3,
354 * so the only reason to push packet (copy) to host is M_BCAST flag.
355 */
356int
357ether_output2(struct ifnet *ifp, struct mbuf *m, struct nhop_prepend *nh,int af)
358{
359 int error;
360
361#ifdef MAC
362 error = mac_ifnet_check_transmit(ifp, m);
363 if (error)
364 senderr(error);
365#endif
366
367 M_PROFILE(m);
368 if (ifp->if_flags & IFF_MONITOR)
369 senderr(ENETDOWN);
370 if (!((ifp->if_flags & IFF_UP) &&
371 (ifp->if_drv_flags & IFF_DRV_RUNNING)))
372 senderr(ENETDOWN);
373
374 if ((ifp->if_flags & IFF_SIMPLEX) && (m->m_flags & M_BCAST)) {
375 /* We have to copy frame to-us */
376 if (loopback_frame(NH_LIFP(nh), m, af, nh->nh_count) != 0)
377 return (0);
378 }
379
380 /*
381 * Bridges require special output handling.
382 */
383 if (ifp->if_bridge) {
384 BRIDGE_OUTPUT(ifp, m, error);
385 return (error);
386 }
387
388#if defined(INET) || defined(INET6)
389 if (ifp->if_carp) {
390 struct sockaddr_in dst;
391 memset(&dst, 0, sizeof(dst));
392 //dst.sin_addr =
393 error = (*carp_output_p)(ifp, m,
394 (const struct sockaddr *)&dst);
395 if (error != 0)
396 goto bad;
397 }
398#endif
399
400 /* Handle ng_ether(4) processing, if any */
401 if (IFP2AC(ifp)->ac_netgraph != NULL) {
402 KASSERT(ng_ether_output_p != NULL,
403 ("ng_ether_output_p is NULL"));
404 if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) {
405bad: if (m != NULL)
406 m_freem(m);
407 return (error);
408 }
409 if (m == NULL)
410 return (0);
411 }
412
413 /* Continue with link-layer output */
414 return (ether_output_frame(ifp, m));
415}
416
417static int
418loopback_frame(struct ifnet *ifp, struct mbuf *m, int family, int hlen)
419{
420 struct ether_header *eh;
421
422 if (m->m_flags & M_BCAST) {
423 struct mbuf *n;
424
425 /*
426 * Because if_simloop() modifies the packet, we need a
427 * writable copy through m_dup() instead of a readonly
428 * one as m_copy[m] would give us. The alternative would
429 * be to modify if_simloop() to handle the readonly mbuf,
430 * but performancewise it is mostly equivalent (trading
431 * extra data copying vs. extra locking).
432 *
433 * XXX This is a local workaround. A number of less
434 * often used kernel parts suffer from the same bug.
435 * See PR kern/105943 for a proposed general solution.
436 */
437 if ((n = m_dup(m, M_NOWAIT)) != NULL) {
438 update_mbuf_csumflags(m, n);
439 if_simloop(ifp, n, family, hlen);
440 } else
441 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
442 } else {
443 eh = mtod(m, struct ether_header *);
444 if (bcmp(eh->ether_dhost, eh->ether_shost,
445 ETHER_ADDR_LEN) == 0) {
446 update_mbuf_csumflags(m, m);
447 if_simloop(ifp, m, family, hlen);
448 return (1);
449 }
450 }
451
452 return (0);
453}
454
455/*
456 * Ethernet link layer output routine to send a raw frame to the device.
457 *
458 * This assumes that the 14 byte Ethernet header is present and contiguous
459 * in the first mbuf (if BRIDGE'ing).
460 */
461int
462ether_output_frame(struct ifnet *ifp, struct mbuf *m)
463{

--- 158 unchanged lines hidden (view full) ---

622 ETHER_HDR_LEN - ETHER_TYPE_LEN);
623 m_adj(m, ETHER_VLAN_ENCAP_LEN);
624 eh = mtod(m, struct ether_header *);
625 }
626
627 M_SETFIB(m, ifp->if_fib);
628
629 /* Allow ng_ether(4) to claim this frame. */
347 * Ethernet link layer output routine to send a raw frame to the device.
348 *
349 * This assumes that the 14 byte Ethernet header is present and contiguous
350 * in the first mbuf (if BRIDGE'ing).
351 */
352int
353ether_output_frame(struct ifnet *ifp, struct mbuf *m)
354{

--- 158 unchanged lines hidden (view full) ---

513 ETHER_HDR_LEN - ETHER_TYPE_LEN);
514 m_adj(m, ETHER_VLAN_ENCAP_LEN);
515 eh = mtod(m, struct ether_header *);
516 }
517
518 M_SETFIB(m, ifp->if_fib);
519
520 /* Allow ng_ether(4) to claim this frame. */
630 if (IFP2AC(ifp)->ac_netgraph != NULL) {
521 if (ifp->if_l2com != NULL) {
631 KASSERT(ng_ether_input_p != NULL,
632 ("%s: ng_ether_input_p is NULL", __func__));
633 m->m_flags &= ~M_PROMISC;
634 (*ng_ether_input_p)(ifp, &m);
635 if (m == NULL) {
636 CURVNET_RESTORE();
637 return;
638 }

--- 242 unchanged lines hidden (view full) ---

881 return;
882
883discard:
884 /*
885 * Packet is to be discarded. If netgraph is present,
886 * hand the packet to it for last chance processing;
887 * otherwise dispose of it.
888 */
522 KASSERT(ng_ether_input_p != NULL,
523 ("%s: ng_ether_input_p is NULL", __func__));
524 m->m_flags &= ~M_PROMISC;
525 (*ng_ether_input_p)(ifp, &m);
526 if (m == NULL) {
527 CURVNET_RESTORE();
528 return;
529 }

--- 242 unchanged lines hidden (view full) ---

772 return;
773
774discard:
775 /*
776 * Packet is to be discarded. If netgraph is present,
777 * hand the packet to it for last chance processing;
778 * otherwise dispose of it.
779 */
889 if (IFP2AC(ifp)->ac_netgraph != NULL) {
780 if (ifp->if_l2com != NULL) {
890 KASSERT(ng_ether_input_orphan_p != NULL,
891 ("ng_ether_input_orphan_p is NULL"));
892 /*
893 * Put back the ethernet header so netgraph has a
894 * consistent view of inbound packets.
895 */
896 M_PREPEND(m, ETHER_HDR_LEN, M_NOWAIT);
897 (*ng_ether_input_orphan_p)(ifp, m);

--- 69 unchanged lines hidden (view full) ---

967void
968ether_ifdetach(struct ifnet *ifp)
969{
970 struct sockaddr_dl *sdl;
971
972 sdl = (struct sockaddr_dl *)(ifp->if_addr->ifa_addr);
973 uuid_ether_del(LLADDR(sdl));
974
781 KASSERT(ng_ether_input_orphan_p != NULL,
782 ("ng_ether_input_orphan_p is NULL"));
783 /*
784 * Put back the ethernet header so netgraph has a
785 * consistent view of inbound packets.
786 */
787 M_PREPEND(m, ETHER_HDR_LEN, M_NOWAIT);
788 (*ng_ether_input_orphan_p)(ifp, m);

--- 69 unchanged lines hidden (view full) ---

858void
859ether_ifdetach(struct ifnet *ifp)
860{
861 struct sockaddr_dl *sdl;
862
863 sdl = (struct sockaddr_dl *)(ifp->if_addr->ifa_addr);
864 uuid_ether_del(LLADDR(sdl));
865
975 if (IFP2AC(ifp)->ac_netgraph != NULL) {
866 if (ifp->if_l2com != NULL) {
976 KASSERT(ng_ether_detach_p != NULL,
977 ("ng_ether_detach_p is NULL"));
978 (*ng_ether_detach_p)(ifp);
979 }
980
981 bpfdetach(ifp);
982 if_detach(ifp);
983}
984
985#ifdef VIMAGE
986void
987ether_reassign(struct ifnet *ifp, struct vnet *new_vnet, char *unused __unused)
988{
989
867 KASSERT(ng_ether_detach_p != NULL,
868 ("ng_ether_detach_p is NULL"));
869 (*ng_ether_detach_p)(ifp);
870 }
871
872 bpfdetach(ifp);
873 if_detach(ifp);
874}
875
876#ifdef VIMAGE
877void
878ether_reassign(struct ifnet *ifp, struct vnet *new_vnet, char *unused __unused)
879{
880
990 if (IFP2AC(ifp)->ac_netgraph != NULL) {
881 if (ifp->if_l2com != NULL) {
991 KASSERT(ng_ether_detach_p != NULL,
992 ("ng_ether_detach_p is NULL"));
993 (*ng_ether_detach_p)(ifp);
994 }
995
996 if (ng_ether_attach_p != NULL) {
997 CURVNET_SET_QUIET(new_vnet);
998 (*ng_ether_attach_p)(ifp);

--- 194 unchanged lines hidden (view full) ---

1193 /*
1194 * Well, the text isn't quite right, but it's the name
1195 * that counts...
1196 */
1197 return EAFNOSUPPORT;
1198 }
1199}
1200
882 KASSERT(ng_ether_detach_p != NULL,
883 ("ng_ether_detach_p is NULL"));
884 (*ng_ether_detach_p)(ifp);
885 }
886
887 if (ng_ether_attach_p != NULL) {
888 CURVNET_SET_QUIET(new_vnet);
889 (*ng_ether_attach_p)(ifp);

--- 194 unchanged lines hidden (view full) ---

1084 /*
1085 * Well, the text isn't quite right, but it's the name
1086 * that counts...
1087 */
1088 return EAFNOSUPPORT;
1089 }
1090}
1091
1201static void*
1202ether_alloc(u_char type, struct ifnet *ifp)
1203{
1204 struct arpcom *ac;
1205
1206 ac = malloc(sizeof(struct arpcom), M_ARPCOM, M_WAITOK | M_ZERO);
1207 ac->ac_ifp = ifp;
1208
1209 return (ac);
1210}
1211
1212static void
1213ether_free(void *com, u_char type)
1214{
1215
1216 free(com, M_ARPCOM);
1217}
1218
1219static int
1220ether_modevent(module_t mod, int type, void *data)
1221{
1222
1223 switch (type) {
1224 case MOD_LOAD:
1225 if_register_com_alloc(IFT_ETHER, ether_alloc, ether_free);
1226 break;
1227 case MOD_UNLOAD:
1228 if_deregister_com_alloc(IFT_ETHER);
1229 break;
1230 default:
1231 return EOPNOTSUPP;
1232 }
1233
1234 return (0);
1235}
1236
1237static moduledata_t ether_mod = {
1092static moduledata_t ether_mod = {
1238 "ether",
1239 ether_modevent,
1240 0
1093 .name = "ether",
1241};
1242
1243void
1244ether_vlan_mtap(struct bpf_if *bp, struct mbuf *m, void *data, u_int dlen)
1245{
1246 struct ether_vlan_header vlan;
1247 struct mbuf mv, mb;
1248

--- 64 unchanged lines hidden ---
1094};
1095
1096void
1097ether_vlan_mtap(struct bpf_if *bp, struct mbuf *m, void *data, u_int dlen)
1098{
1099 struct ether_vlan_header vlan;
1100 struct mbuf mv, mb;
1101

--- 64 unchanged lines hidden ---