Deleted Added
full compact
if.c (130585) if.c (130933)
1/*
2 * Copyright (c) 1980, 1986, 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

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

22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)if.c 8.5 (Berkeley) 1/9/95
1/*
2 * Copyright (c) 1980, 1986, 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

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

22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)if.c 8.5 (Berkeley) 1/9/95
30 * $FreeBSD: head/sys/net/if.c 130585 2004-06-16 09:47:26Z phk $
30 * $FreeBSD: head/sys/net/if.c 130933 2004-06-22 20:13:25Z brooks $
31 */
32
33#include "opt_compat.h"
34#include "opt_inet6.h"
35#include "opt_inet.h"
36#include "opt_mac.h"
37
38#include <sys/param.h>

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

51#include <sys/syslog.h>
52#include <sys/sysctl.h>
53#include <sys/domain.h>
54#include <sys/jail.h>
55#include <machine/stdarg.h>
56
57#include <net/if.h>
58#include <net/if_arp.h>
31 */
32
33#include "opt_compat.h"
34#include "opt_inet6.h"
35#include "opt_inet.h"
36#include "opt_mac.h"
37
38#include <sys/param.h>

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

51#include <sys/syslog.h>
52#include <sys/sysctl.h>
53#include <sys/domain.h>
54#include <sys/jail.h>
55#include <machine/stdarg.h>
56
57#include <net/if.h>
58#include <net/if_arp.h>
59#include <net/if_clone.h>
59#include <net/if_dl.h>
60#include <net/if_types.h>
61#include <net/if_var.h>
62#include <net/radix.h>
63#include <net/route.h>
64
65#if defined(INET) || defined(INET6)
66/*XXX*/

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

85static void if_check(void *);
86static int if_findindex(struct ifnet *);
87static void if_qflush(struct ifaltq *);
88static void if_route(struct ifnet *, int flag, int fam);
89static void if_slowtimo(void *);
90static void if_unroute(struct ifnet *, int flag, int fam);
91static void link_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
92static int if_rtdel(struct radix_node *, void *);
60#include <net/if_dl.h>
61#include <net/if_types.h>
62#include <net/if_var.h>
63#include <net/radix.h>
64#include <net/route.h>
65
66#if defined(INET) || defined(INET6)
67/*XXX*/

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

86static void if_check(void *);
87static int if_findindex(struct ifnet *);
88static void if_qflush(struct ifaltq *);
89static void if_route(struct ifnet *, int flag, int fam);
90static void if_slowtimo(void *);
91static void if_unroute(struct ifnet *, int flag, int fam);
92static void link_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
93static int if_rtdel(struct radix_node *, void *);
93static struct if_clone *if_clone_lookup(const char *, int *);
94static int if_clone_list(struct if_clonereq *);
95static int ifhwioctl(u_long, struct ifnet *, caddr_t, struct thread *);
96#ifdef INET6
97/*
98 * XXX: declare here to avoid to include many inet6 related files..
99 * should be more generalized?
100 */
101extern void nd6_setmtu(struct ifnet *);
102#endif
103
104int if_index = 0;
105struct ifindex_entry *ifindex_table = NULL;
106int ifqmaxlen = IFQ_MAXLEN;
107struct ifnethead ifnet; /* depend on static init XXX */
108struct mtx ifnet_lock;
94static int ifhwioctl(u_long, struct ifnet *, caddr_t, struct thread *);
95#ifdef INET6
96/*
97 * XXX: declare here to avoid to include many inet6 related files..
98 * should be more generalized?
99 */
100extern void nd6_setmtu(struct ifnet *);
101#endif
102
103int if_index = 0;
104struct ifindex_entry *ifindex_table = NULL;
105int ifqmaxlen = IFQ_MAXLEN;
106struct ifnethead ifnet; /* depend on static init XXX */
107struct mtx ifnet_lock;
109static int if_cloners_count;
110LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
111
112static int if_indexlim = 8;
113static struct klist ifklist;
114
115static void filt_netdetach(struct knote *kn);
116static int filt_netdev(struct knote *kn, long hint);
117
118static struct filterops netdev_filtops =
119 { 1, NULL, filt_netdetach, filt_netdev };
120
121/*
122 * System initialization
123 */
124SYSINIT(interfaces, SI_SUB_INIT_IF, SI_ORDER_FIRST, if_init, NULL)
125SYSINIT(interface_check, SI_SUB_PROTO_IF, SI_ORDER_FIRST, if_check, NULL)
126
127MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
128MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
108
109static int if_indexlim = 8;
110static struct klist ifklist;
111
112static void filt_netdetach(struct knote *kn);
113static int filt_netdev(struct knote *kn, long hint);
114
115static struct filterops netdev_filtops =
116 { 1, NULL, filt_netdetach, filt_netdev };
117
118/*
119 * System initialization
120 */
121SYSINIT(interfaces, SI_SUB_INIT_IF, SI_ORDER_FIRST, if_init, NULL)
122SYSINIT(interface_check, SI_SUB_PROTO_IF, SI_ORDER_FIRST, if_check, NULL)
123
124MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
125MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
129MALLOC_DEFINE(M_CLONE, "clone", "interface cloning framework");
130
131static d_open_t netopen;
132static d_close_t netclose;
133static d_ioctl_t netioctl;
134static d_kqfilter_t netkqfilter;
135
136static struct cdevsw net_cdevsw = {
137 .d_version = D_VERSION,

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

258{
259
260 IFNET_LOCK_INIT();
261 TAILQ_INIT(&ifnet);
262 SLIST_INIT(&ifklist);
263 if_grow(); /* create initial table */
264 ifdev_byindex(0) = make_dev(&net_cdevsw, 0,
265 UID_ROOT, GID_WHEEL, 0600, "network");
126
127static d_open_t netopen;
128static d_close_t netclose;
129static d_ioctl_t netioctl;
130static d_kqfilter_t netkqfilter;
131
132static struct cdevsw net_cdevsw = {
133 .d_version = D_VERSION,

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

254{
255
256 IFNET_LOCK_INIT();
257 TAILQ_INIT(&ifnet);
258 SLIST_INIT(&ifklist);
259 if_grow(); /* create initial table */
260 ifdev_byindex(0) = make_dev(&net_cdevsw, 0,
261 UID_ROOT, GID_WHEEL, 0600, "network");
262 if_clone_init();
266}
267
268static void
269if_grow(void)
270{
271 u_int n;
272 struct ifindex_entry *e;
273

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

663 if (err) {
664 log(LOG_WARNING, "if_rtdel: error %d\n", err);
665 }
666 }
667
668 return (0);
669}
670
263}
264
265static void
266if_grow(void)
267{
268 u_int n;
269 struct ifindex_entry *e;
270

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

660 if (err) {
661 log(LOG_WARNING, "if_rtdel: error %d\n", err);
662 }
663 }
664
665 return (0);
666}
667
671/*
672 * Create a clone network interface.
673 */
674int
675if_clone_create(char *name, int len)
676{
677 struct if_clone *ifc;
678 char *dp;
679 int wildcard, bytoff, bitoff;
680 int unit;
681 int err;
682
683 ifc = if_clone_lookup(name, &unit);
684 if (ifc == NULL)
685 return (EINVAL);
686
687 if (ifunit(name) != NULL)
688 return (EEXIST);
689
690 bytoff = bitoff = 0;
691 wildcard = (unit < 0);
692 /*
693 * Find a free unit if none was given.
694 */
695 if (wildcard) {
696 while ((bytoff < ifc->ifc_bmlen)
697 && (ifc->ifc_units[bytoff] == 0xff))
698 bytoff++;
699 if (bytoff >= ifc->ifc_bmlen)
700 return (ENOSPC);
701 while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0)
702 bitoff++;
703 unit = (bytoff << 3) + bitoff;
704 }
705
706 if (unit > ifc->ifc_maxunit)
707 return (ENXIO);
708
709 err = (*ifc->ifc_create)(ifc, unit);
710 if (err != 0)
711 return (err);
712
713 if (!wildcard) {
714 bytoff = unit >> 3;
715 bitoff = unit - (bytoff << 3);
716 }
717
718 /*
719 * Allocate the unit in the bitmap.
720 */
721 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0,
722 ("%s: bit is already set", __func__));
723 ifc->ifc_units[bytoff] |= (1 << bitoff);
724
725 /* In the wildcard case, we need to update the name. */
726 if (wildcard) {
727 for (dp = name; *dp != '\0'; dp++);
728 if (snprintf(dp, len - (dp-name), "%d", unit) >
729 len - (dp-name) - 1) {
730 /*
731 * This can only be a programmer error and
732 * there's no straightforward way to recover if
733 * it happens.
734 */
735 panic("if_clone_create(): interface name too long");
736 }
737
738 }
739
740 return (0);
741}
742
743/*
744 * Destroy a clone network interface.
745 */
746int
747if_clone_destroy(const char *name)
748{
749 struct if_clone *ifc;
750 struct ifnet *ifp;
751 int bytoff, bitoff;
752 int unit;
753
754 ifp = ifunit(name);
755 if (ifp == NULL)
756 return (ENXIO);
757
758 unit = ifp->if_dunit;
759
760 ifc = if_clone_lookup(ifp->if_dname, NULL);
761 if (ifc == NULL)
762 return (EINVAL);
763
764 if (ifc->ifc_destroy == NULL)
765 return (EOPNOTSUPP);
766
767 (*ifc->ifc_destroy)(ifp);
768
769 /*
770 * Compute offset in the bitmap and deallocate the unit.
771 */
772 bytoff = unit >> 3;
773 bitoff = unit - (bytoff << 3);
774 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0,
775 ("%s: bit is already cleared", __func__));
776 ifc->ifc_units[bytoff] &= ~(1 << bitoff);
777 return (0);
778}
779
780/*
781 * Look up a network interface cloner.
782 */
783static struct if_clone *
784if_clone_lookup(const char *name, int *unitp)
785{
786 struct if_clone *ifc;
787 const char *cp;
788 int i;
789
790 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) {
791 for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {
792 if (ifc->ifc_name[i] != *cp)
793 goto next_ifc;
794 }
795 goto found_name;
796 next_ifc:
797 ifc = LIST_NEXT(ifc, ifc_list);
798 }
799
800 /* No match. */
801 return ((struct if_clone *)NULL);
802
803 found_name:
804 if (*cp == '\0') {
805 i = -1;
806 } else {
807 for (i = 0; *cp != '\0'; cp++) {
808 if (*cp < '0' || *cp > '9') {
809 /* Bogus unit number. */
810 return (NULL);
811 }
812 i = (i * 10) + (*cp - '0');
813 }
814 }
815
816 if (unitp != NULL)
817 *unitp = i;
818 return (ifc);
819}
820
821/*
822 * Register a network interface cloner.
823 */
824void
825if_clone_attach(struct if_clone *ifc)
826{
827 int bytoff, bitoff;
828 int err;
829 int len, maxclone;
830 int unit;
831
832 KASSERT(ifc->ifc_minifs - 1 <= ifc->ifc_maxunit,
833 ("%s: %s requested more units then allowed (%d > %d)",
834 __func__, ifc->ifc_name, ifc->ifc_minifs,
835 ifc->ifc_maxunit + 1));
836 /*
837 * Compute bitmap size and allocate it.
838 */
839 maxclone = ifc->ifc_maxunit + 1;
840 len = maxclone >> 3;
841 if ((len << 3) < maxclone)
842 len++;
843 ifc->ifc_units = malloc(len, M_CLONE, M_WAITOK | M_ZERO);
844 ifc->ifc_bmlen = len;
845
846 LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
847 if_cloners_count++;
848
849 for (unit = 0; unit < ifc->ifc_minifs; unit++) {
850 err = (*ifc->ifc_create)(ifc, unit);
851 KASSERT(err == 0,
852 ("%s: failed to create required interface %s%d",
853 __func__, ifc->ifc_name, unit));
854
855 /* Allocate the unit in the bitmap. */
856 bytoff = unit >> 3;
857 bitoff = unit - (bytoff << 3);
858 ifc->ifc_units[bytoff] |= (1 << bitoff);
859 }
860 EVENTHANDLER_INVOKE(if_clone_event, ifc);
861}
862
863/*
864 * Unregister a network interface cloner.
865 */
866void
867if_clone_detach(struct if_clone *ifc)
868{
869
870 LIST_REMOVE(ifc, ifc_list);
871 free(ifc->ifc_units, M_CLONE);
872 if_cloners_count--;
873}
874
875/*
876 * Provide list of interface cloners to userspace.
877 */
878static int
879if_clone_list(struct if_clonereq *ifcr)
880{
881 char outbuf[IFNAMSIZ], *dst;
882 struct if_clone *ifc;
883 int count, error = 0;
884
885 ifcr->ifcr_total = if_cloners_count;
886 if ((dst = ifcr->ifcr_buffer) == NULL) {
887 /* Just asking how many there are. */
888 return (0);
889 }
890
891 if (ifcr->ifcr_count < 0)
892 return (EINVAL);
893
894 count = (if_cloners_count < ifcr->ifcr_count) ?
895 if_cloners_count : ifcr->ifcr_count;
896
897 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
898 ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
899 strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
900 error = copyout(outbuf, dst, IFNAMSIZ);
901 if (error)
902 break;
903 }
904
905 return (error);
906}
907
908#define equal(a1, a2) (bcmp((a1), (a2), ((a1))->sa_len) == 0)
909
910/*
911 * Locate an interface based on a complete address.
912 */
913/*ARGSUSED*/
914struct ifaddr *
915ifa_ifwithaddr(struct sockaddr *addr)

--- 1169 unchanged lines hidden ---
668#define equal(a1, a2) (bcmp((a1), (a2), ((a1))->sa_len) == 0)
669
670/*
671 * Locate an interface based on a complete address.
672 */
673/*ARGSUSED*/
674struct ifaddr *
675ifa_ifwithaddr(struct sockaddr *addr)

--- 1169 unchanged lines hidden ---