summaryrefslogtreecommitdiff
path: root/net-mgmt/net-snmp-devel/files/patch-interfaces.c
blob: bc56d6ca3a3e027f16571043c6fa95af1cf0dcd4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
--- agent/mibgroup/mibII/interfaces.c.orig	Wed Oct 26 00:52:19 2005
+++ agent/mibgroup/mibII/interfaces.c	Tue Feb 27 20:44:48 2007
@@ -395,6 +395,133 @@
     return NULL;
 }
 
+#if defined(freebsd2)
+static char    *physaddrbuf;
+static int      nphysaddrs;
+struct sockaddr_dl **physaddrs;
+
+void
+init_interfaces_setup(void)
+{
+    int             naddrs, ilen, bit;
+    static int      mib[6]
+    = { CTL_NET, PF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
+    char           *cp;
+    size_t          len;
+    struct rt_msghdr *rtm;
+    struct if_msghdr *ifm;
+    struct ifa_msghdr *ifam;
+    struct sockaddr *sa;
+
+    naddrs = 0;
+    if (physaddrs)
+        free(physaddrs);
+    if (physaddrbuf)
+        free(physaddrbuf);
+    physaddrbuf = 0;
+    physaddrs = 0;
+    nphysaddrs = 0;
+    len = 0;
+    if (sysctl(mib, 6, 0, &len, 0, 0) < 0)
+        return;
+
+    cp = physaddrbuf = malloc(len);
+    if (physaddrbuf == 0)
+        return;
+    if (sysctl(mib, 6, physaddrbuf, &len, 0, 0) < 0) {
+        free(physaddrbuf);
+        physaddrbuf = 0;
+        return;
+    }
+
+  loop:
+    ilen = len;
+    cp = physaddrbuf;
+    while (ilen > 0) {
+        rtm = (struct rt_msghdr *) cp;
+        if (rtm->rtm_version != RTM_VERSION || rtm->rtm_type != RTM_IFINFO) {
+            free(physaddrs);
+            physaddrs = 0;
+            free(physaddrbuf);
+            physaddrbuf = 0;
+        }
+        ifm = (struct if_msghdr *) rtm;
+#if defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
+        if (physaddrs != 0)
+            physaddrs[naddrs] = (void *) (ifm + 1);
+        naddrs++;
+#endif
+        ilen -= ifm->ifm_msglen;
+        cp += ifm->ifm_msglen;
+        rtm = (struct rt_msghdr *) cp;
+        while (ilen > 0 && rtm->rtm_type == RTM_NEWADDR) {
+#if defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
+            ilen -= rtm->rtm_msglen;
+            cp += rtm->rtm_msglen;
+#else
+            int             is_alias = 0;
+            ifam = (struct ifa_msghdr *) rtm;
+            ilen -= sizeof(*ifam);
+            cp += sizeof(*ifam);
+            sa = (struct sockaddr *) cp;
+#define ROUND(x) (((x) + sizeof(long) - 1) & ~sizeof(long))
+            for (bit = 1; bit && ilen > 0; bit <<= 1) {
+                if (!(ifam->ifam_addrs & bit))
+                    continue;
+                ilen -= ROUND(sa->sa_len);
+                cp += ROUND(sa->sa_len);
+
+                if (bit == RTA_IFA) {
+                    if (physaddrs)
+#define satosdl(sa) ((struct sockaddr_dl *)(sa))
+                        physaddrs[naddrs++]
+                            = satosdl(sa);
+                    else
+                        naddrs++;
+                }
+                sa = (struct sockaddr *) cp;
+            }
+#endif
+            rtm = (struct rt_msghdr *) cp;
+        }
+    }
+    if (physaddrs) {
+        nphysaddrs = naddrs;
+        return;
+    }
+    physaddrs = malloc(naddrs * sizeof(*physaddrs));
+    if (physaddrs == 0)
+        return;
+    naddrs = 0;
+    goto loop;
+
+}
+
+static int
+get_phys_address(int iindex, char **ap, int *len)
+{
+    int             i;
+    int             once = 1;
+
+    do {
+        for (i = 0; i < nphysaddrs; i++) {
+            if (physaddrs[i]->sdl_index == iindex)
+                break;
+        }
+        if (i < nphysaddrs)
+            break;
+        init_interfaces_setup();
+    } while (once--);
+
+    if (i < nphysaddrs) {
+        *ap = LLADDR(physaddrs[i]);
+        *len = physaddrs[i]->sdl_alen;
+        return 0;
+    }
+    return -1;
+}
+#endif
+
 #ifdef USE_SYSCTL_IFLIST
 
 static u_char  *if_list = 0;
@@ -603,10 +730,20 @@
         }
         return (u_char *) & long_return;
     case IFPHYSADDRESS:
+#if defined(freebsd2)
+        {
+            char           *cp;
+            if (get_phys_address(interface, &cp, var_len))
+                return NULL;
+            else
+                return cp;
+        }
+#else
         /*
          * XXX 
          */
         return NULL;
+#endif
     case IFADMINSTATUS:
         long_return = if_msg.ifm_flags & IFF_UP ? 1 : 2;
         return (u_char *) & long_return;