File: | net/if_mpe.c |
Warning: | line 258, column 2 Value stored to 'error' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: if_mpe.c,v 1.105 2024/01/01 18:47:02 mvs Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@spootnik.org> |
5 | * |
6 | * Permission to use, copy, modify, and distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above |
8 | * copyright notice and this permission notice appear in all copies. |
9 | * |
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ |
18 | |
19 | #include <sys/param.h> |
20 | #include <sys/systm.h> |
21 | #include <sys/mbuf.h> |
22 | #include <sys/socket.h> |
23 | #include <sys/sockio.h> |
24 | #include <sys/ioctl.h> |
25 | |
26 | #include <net/if.h> |
27 | #include <net/if_dl.h> |
28 | #include <net/if_var.h> |
29 | #include <net/if_types.h> |
30 | #include <net/netisr.h> |
31 | #include <net/route.h> |
32 | |
33 | #include <netinet/in.h> |
34 | #include <netinet/ip.h> |
35 | |
36 | #ifdef INET61 |
37 | #include <netinet/ip6.h> |
38 | #endif /* INET6 */ |
39 | |
40 | #include "bpfilter.h" |
41 | #if NBPFILTER1 > 0 |
42 | #include <net/bpf.h> |
43 | #endif |
44 | |
45 | #include <netmpls/mpls.h> |
46 | |
47 | |
48 | |
49 | #ifdef MPLS_DEBUG |
50 | #define DPRINTF(x) do { if (mpedebug) printf x ; } while (0) |
51 | #else |
52 | #define DPRINTF(x) |
53 | #endif |
54 | |
55 | struct mpe_softc { |
56 | struct ifnet sc_if; /* the interface */ |
57 | int sc_txhprio; |
58 | int sc_rxhprio; |
59 | unsigned int sc_rdomain; |
60 | struct ifaddr sc_ifa; |
61 | struct sockaddr_mpls sc_smpls; |
62 | |
63 | int sc_dead; |
64 | }; |
65 | |
66 | #define MPE_HDRLENsizeof(struct shim_hdr) sizeof(struct shim_hdr) |
67 | #define MPE_MTU1500 1500 |
68 | #define MPE_MTU_MIN256 256 |
69 | #define MPE_MTU_MAX8192 8192 |
70 | |
71 | void mpeattach(int); |
72 | int mpe_output(struct ifnet *, struct mbuf *, struct sockaddr *, |
73 | struct rtentry *); |
74 | int mpe_ioctl(struct ifnet *, u_long, caddr_t); |
75 | void mpe_start(struct ifnet *); |
76 | int mpe_clone_create(struct if_clone *, int); |
77 | int mpe_clone_destroy(struct ifnet *); |
78 | void mpe_input(struct ifnet *, struct mbuf *); |
79 | |
80 | struct if_clone mpe_cloner = |
81 | IF_CLONE_INITIALIZER("mpe", mpe_clone_create, mpe_clone_destroy){ .ifc_list = { ((void *)0), ((void *)0) }, .ifc_name = "mpe" , .ifc_namelen = sizeof("mpe") - 1, .ifc_create = mpe_clone_create , .ifc_destroy = mpe_clone_destroy, }; |
82 | |
83 | extern int mpls_mapttl_ip; |
84 | #ifdef INET61 |
85 | extern int mpls_mapttl_ip6; |
86 | #endif |
87 | |
88 | void |
89 | mpeattach(int nmpe) |
90 | { |
91 | if_clone_attach(&mpe_cloner); |
92 | } |
93 | |
94 | int |
95 | mpe_clone_create(struct if_clone *ifc, int unit) |
96 | { |
97 | struct mpe_softc *sc; |
98 | struct ifnet *ifp; |
99 | |
100 | sc = malloc(sizeof(*sc), M_DEVBUF2, M_WAITOK0x0001|M_CANFAIL0x0004|M_ZERO0x0008); |
101 | if (sc == NULL((void *)0)) |
102 | return (ENOMEM12); |
103 | |
104 | ifp = &sc->sc_if; |
105 | snprintf(ifp->if_xname, sizeof ifp->if_xname, "mpe%d", unit); |
106 | ifp->if_flags = IFF_POINTOPOINT0x10; |
107 | ifp->if_xflags = IFXF_CLONED0x2; |
108 | ifp->if_softc = sc; |
109 | ifp->if_mtuif_data.ifi_mtu = MPE_MTU1500; |
110 | ifp->if_ioctl = mpe_ioctl; |
111 | ifp->if_bpf_mtap = p2p_bpf_mtap; |
112 | ifp->if_input = p2p_input; |
113 | ifp->if_output = mpe_output; |
114 | ifp->if_start = mpe_start; |
115 | ifp->if_typeif_data.ifi_type = IFT_MPLS0xa6; |
116 | ifp->if_hdrlenif_data.ifi_hdrlen = MPE_HDRLENsizeof(struct shim_hdr); |
117 | |
118 | sc->sc_dead = 0; |
119 | |
120 | if_counters_alloc(ifp); |
121 | if_attach(ifp); |
122 | if_alloc_sadl(ifp); |
123 | |
124 | #if NBPFILTER1 > 0 |
125 | bpfattach(&ifp->if_bpf, ifp, DLT_LOOP12, sizeof(u_int32_t)); |
126 | #endif |
127 | |
128 | sc->sc_txhprio = 0; |
129 | sc->sc_rxhprio = IF_HDRPRIO_PACKET-1; |
130 | sc->sc_rdomain = 0; |
131 | refcnt_init_trace(&sc->sc_ifa.ifa_refcnt, DT_REFCNT_IDX_IFADDR2); |
132 | sc->sc_ifa.ifa_ifp = ifp; |
133 | sc->sc_ifa.ifa_addr = sdltosa(ifp->if_sadl); |
134 | sc->sc_smpls.smpls_len = sizeof(sc->sc_smpls); |
135 | sc->sc_smpls.smpls_family = AF_MPLS33; |
136 | |
137 | return (0); |
138 | } |
139 | |
140 | int |
141 | mpe_clone_destroy(struct ifnet *ifp) |
142 | { |
143 | struct mpe_softc *sc = ifp->if_softc; |
144 | |
145 | NET_LOCK()do { rw_enter_write(&netlock); } while (0); |
146 | CLR(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) &= ~(0x40)); |
147 | sc->sc_dead = 1; |
148 | |
149 | if (sc->sc_smpls.smpls_label) { |
150 | rt_ifa_del(&sc->sc_ifa, RTF_MPLS0x100000|RTF_LOCAL0x200000, |
151 | smplstosa(&sc->sc_smpls)((struct sockaddr *)(&sc->sc_smpls)), sc->sc_rdomain); |
152 | } |
153 | NET_UNLOCK()do { rw_exit_write(&netlock); } while (0); |
154 | |
155 | ifq_barrier(&ifp->if_snd); |
156 | |
157 | if_detach(ifp); |
158 | if (refcnt_rele(&sc->sc_ifa.ifa_refcnt) == 0) { |
159 | panic("%s: ifa refcnt has %u refs", __func__, |
160 | sc->sc_ifa.ifa_refcnt.r_refs); |
161 | } |
162 | free(sc, M_DEVBUF2, sizeof *sc); |
163 | return (0); |
164 | } |
165 | |
166 | /* |
167 | * Start output on the mpe interface. |
168 | */ |
169 | void |
170 | mpe_start(struct ifnet *ifp) |
171 | { |
172 | struct mpe_softc *sc = ifp->if_softc; |
173 | struct mbuf *m; |
174 | struct sockaddr *sa; |
175 | struct sockaddr smpls = { .sa_family = AF_MPLS33 }; |
176 | struct rtentry *rt; |
177 | struct ifnet *ifp0; |
178 | |
179 | while ((m = ifq_dequeue(&ifp->if_snd)) != NULL((void *)0)) { |
180 | sa = mtod(m, struct sockaddr *)((struct sockaddr *)((m)->m_hdr.mh_data)); |
181 | rt = rtalloc(sa, RT_RESOLVE1, sc->sc_rdomain); |
182 | if (!rtisvalid(rt)) { |
183 | m_freem(m); |
184 | rtfree(rt); |
185 | continue; |
186 | } |
187 | |
188 | ifp0 = if_get(rt->rt_ifidx); |
189 | if (ifp0 == NULL((void *)0)) { |
190 | m_freem(m); |
191 | rtfree(rt); |
192 | continue; |
193 | } |
194 | |
195 | m_adj(m, sa->sa_len); |
196 | |
197 | #if NBPFILTER1 > 0 |
198 | if (ifp->if_bpf) { |
199 | /* remove MPLS label before passing packet to bpf */ |
200 | m->m_datam_hdr.mh_data += sizeof(struct shim_hdr); |
201 | m->m_lenm_hdr.mh_len -= sizeof(struct shim_hdr); |
202 | m->m_pkthdrM_dat.MH.MH_pkthdr.len -= sizeof(struct shim_hdr); |
203 | bpf_mtap_af(ifp->if_bpf, m->m_pkthdrM_dat.MH.MH_pkthdr.ph_family, |
204 | m, BPF_DIRECTION_OUT(1 << 1)); |
205 | m->m_datam_hdr.mh_data -= sizeof(struct shim_hdr); |
206 | m->m_lenm_hdr.mh_len += sizeof(struct shim_hdr); |
207 | m->m_pkthdrM_dat.MH.MH_pkthdr.len += sizeof(struct shim_hdr); |
208 | } |
209 | #endif |
210 | |
211 | m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid = sc->sc_rdomain; |
212 | CLR(m->m_flags, M_BCAST|M_MCAST)((m->m_hdr.mh_flags) &= ~(0x0100|0x0200)); |
213 | |
214 | mpls_output(ifp0, m, &smpls, rt); |
215 | if_put(ifp0); |
216 | rtfree(rt); |
217 | } |
218 | } |
219 | |
220 | int |
221 | mpe_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, |
222 | struct rtentry *rt) |
223 | { |
224 | struct mpe_softc *sc; |
225 | struct rt_mpls *rtmpls; |
226 | struct shim_hdr shim; |
227 | int error; |
228 | int txprio; |
229 | uint8_t ttl = mpls_defttl; |
230 | uint8_t tos, prio; |
231 | size_t ttloff; |
232 | socklen_t slen; |
233 | |
234 | if (!rtisvalid(rt) || !ISSET(rt->rt_flags, RTF_MPLS)((rt->rt_flags) & (0x100000))) { |
235 | m_freem(m); |
236 | return (ENETUNREACH51); |
237 | } |
238 | |
239 | if (dst->sa_family == AF_LINK18 && ISSET(rt->rt_flags, RTF_LOCAL)((rt->rt_flags) & (0x200000))) { |
240 | mpe_input(ifp, m); |
241 | return (0); |
242 | } |
243 | |
244 | #ifdef DIAGNOSTIC1 |
245 | if (ifp->if_rdomainif_data.ifi_rdomain != rtable_l2(m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid)) { |
246 | printf("%s: trying to send packet on wrong domain. " |
247 | "if %d vs. mbuf %d\n", ifp->if_xname, |
248 | ifp->if_rdomainif_data.ifi_rdomain, rtable_l2(m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid)); |
249 | } |
250 | #endif |
251 | |
252 | rtmpls = (struct rt_mpls *)rt->rt_llinfo; |
253 | if (rtmpls->mpls_operation != MPLS_OP_PUSH0x2) { |
254 | m_freem(m); |
255 | return (ENETUNREACH51); |
256 | } |
257 | |
258 | error = 0; |
Value stored to 'error' is never read | |
259 | switch (dst->sa_family) { |
260 | case AF_INET2: { |
261 | struct ip *ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data)); |
262 | tos = ip->ip_tos; |
263 | ttloff = offsetof(struct ip, ip_ttl)__builtin_offsetof(struct ip, ip_ttl); |
264 | slen = sizeof(struct sockaddr_in); |
265 | break; |
266 | } |
267 | #ifdef INET61 |
268 | case AF_INET624: { |
269 | struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data)); |
270 | uint32_t flow = bemtoh32(&ip6->ip6_flow)(__uint32_t)(__builtin_constant_p(*(__uint32_t *)(&ip6-> ip6_ctlun.ip6_un1.ip6_un1_flow)) ? (__uint32_t)(((__uint32_t) (*(__uint32_t *)(&ip6->ip6_ctlun.ip6_un1.ip6_un1_flow) ) & 0xff) << 24 | ((__uint32_t)(*(__uint32_t *)(& ip6->ip6_ctlun.ip6_un1.ip6_un1_flow)) & 0xff00) << 8 | ((__uint32_t)(*(__uint32_t *)(&ip6->ip6_ctlun.ip6_un1 .ip6_un1_flow)) & 0xff0000) >> 8 | ((__uint32_t)(*( __uint32_t *)(&ip6->ip6_ctlun.ip6_un1.ip6_un1_flow)) & 0xff000000) >> 24) : __swap32md(*(__uint32_t *)(&ip6 ->ip6_ctlun.ip6_un1.ip6_un1_flow))); |
271 | tos = flow >> 20; |
272 | ttloff = offsetof(struct ip6_hdr, ip6_hlim)__builtin_offsetof(struct ip6_hdr, ip6_ctlun.ip6_un1.ip6_un1_hlim ); |
273 | slen = sizeof(struct sockaddr_in6); |
274 | break; |
275 | } |
276 | #endif |
277 | default: |
278 | m_freem(m); |
279 | return (EPFNOSUPPORT46); |
280 | } |
281 | |
282 | if (mpls_mapttl_ip) { |
283 | /* assumes the ip header is already contig */ |
284 | ttl = *(mtod(m, uint8_t *)((uint8_t *)((m)->m_hdr.mh_data)) + ttloff); |
285 | } |
286 | |
287 | sc = ifp->if_softc; |
288 | txprio = sc->sc_txhprio; |
289 | |
290 | switch (txprio) { |
291 | case IF_HDRPRIO_PACKET-1: |
292 | prio = m->m_pkthdrM_dat.MH.MH_pkthdr.pf.prio; |
293 | break; |
294 | case IF_HDRPRIO_PAYLOAD-2: |
295 | prio = IFQ_TOS2PRIO(tos)((tos) >> 5); |
296 | break; |
297 | default: |
298 | prio = txprio; |
299 | break; |
300 | } |
301 | |
302 | shim.shim_label = rtmpls->mpls_label | htonl(prio << MPLS_EXP_OFFSET)(__uint32_t)(__builtin_constant_p(prio << 9) ? (__uint32_t )(((__uint32_t)(prio << 9) & 0xff) << 24 | (( __uint32_t)(prio << 9) & 0xff00) << 8 | ((__uint32_t )(prio << 9) & 0xff0000) >> 8 | ((__uint32_t) (prio << 9) & 0xff000000) >> 24) : __swap32md (prio << 9)) | |
303 | MPLS_BOS_MASK((u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t)(0x00000100U )) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x00000100U)) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x00000100U)) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x00000100U)) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x00000100U )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x00000100U )))) | htonl(ttl)(__uint32_t)(__builtin_constant_p(ttl) ? (__uint32_t)(((__uint32_t )(ttl) & 0xff) << 24 | ((__uint32_t)(ttl) & 0xff00 ) << 8 | ((__uint32_t)(ttl) & 0xff0000) >> 8 | ((__uint32_t)(ttl) & 0xff000000) >> 24) : __swap32md (ttl)); |
304 | |
305 | m = m_prepend(m, sizeof(shim), M_NOWAIT0x0002); |
306 | if (m == NULL((void *)0)) { |
307 | error = ENOMEM12; |
308 | goto out; |
309 | } |
310 | *mtod(m, struct shim_hdr *)((struct shim_hdr *)((m)->m_hdr.mh_data)) = shim; |
311 | |
312 | m = m_prepend(m, slen, M_WAITOK0x0001); |
313 | if (m == NULL((void *)0)) { |
314 | error = ENOMEM12; |
315 | goto out; |
316 | } |
317 | memcpy(mtod(m, struct sockaddr *), rt->rt_gateway, slen)__builtin_memcpy((((struct sockaddr *)((m)->m_hdr.mh_data) )), (rt->rt_gateway), (slen)); |
318 | mtod(m, struct sockaddr *)((struct sockaddr *)((m)->m_hdr.mh_data))->sa_len = slen; /* to be sure */ |
319 | |
320 | m->m_pkthdrM_dat.MH.MH_pkthdr.ph_family = dst->sa_family; |
321 | |
322 | error = if_enqueue(ifp, m); |
323 | out: |
324 | if (error) |
325 | ifp->if_oerrorsif_data.ifi_oerrors++; |
326 | return (error); |
327 | } |
328 | |
329 | int |
330 | mpe_set_label(struct mpe_softc *sc, uint32_t label, unsigned int rdomain) |
331 | { |
332 | int error; |
333 | |
334 | if (sc->sc_dead) |
335 | return (ENXIO6); |
336 | |
337 | if (sc->sc_smpls.smpls_label) { |
338 | /* remove old MPLS route */ |
339 | rt_ifa_del(&sc->sc_ifa, RTF_MPLS0x100000|RTF_LOCAL0x200000, |
340 | smplstosa(&sc->sc_smpls)((struct sockaddr *)(&sc->sc_smpls)), sc->sc_rdomain); |
341 | } |
342 | |
343 | /* add new MPLS route */ |
344 | sc->sc_smpls.smpls_label = label; |
345 | sc->sc_rdomain = rdomain; |
346 | |
347 | /* only install with a label or mpe_clone_destroy() will ignore it */ |
348 | if (sc->sc_smpls.smpls_label == MPLS_LABEL2SHIM(0)((__uint32_t)(__builtin_constant_p((0) << 12) ? (__uint32_t )(((__uint32_t)((0) << 12) & 0xff) << 24 | (( __uint32_t)((0) << 12) & 0xff00) << 8 | ((__uint32_t )((0) << 12) & 0xff0000) >> 8 | ((__uint32_t) ((0) << 12) & 0xff000000) >> 24) : __swap32md ((0) << 12)))) |
349 | return 0; |
350 | |
351 | error = rt_ifa_add(&sc->sc_ifa, RTF_MPLS0x100000|RTF_LOCAL0x200000, |
352 | smplstosa(&sc->sc_smpls)((struct sockaddr *)(&sc->sc_smpls)), sc->sc_rdomain); |
353 | if (error) |
354 | sc->sc_smpls.smpls_label = 0; |
355 | |
356 | return (error); |
357 | } |
358 | |
359 | int |
360 | mpe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) |
361 | { |
362 | struct mpe_softc *sc = ifp->if_softc; |
363 | struct ifreq *ifr; |
364 | struct shim_hdr shim; |
365 | int error = 0; |
366 | |
367 | ifr = (struct ifreq *)data; |
368 | switch (cmd) { |
369 | case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((12))): |
370 | break; |
371 | case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((16))): |
372 | if (ifp->if_flags & IFF_UP0x1) |
373 | ifp->if_flags |= IFF_RUNNING0x40; |
374 | else |
375 | ifp->if_flags &= ~IFF_RUNNING0x40; |
376 | break; |
377 | case SIOCSIFMTU((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((127))): |
378 | if (ifr->ifr_mtuifr_ifru.ifru_metric < MPE_MTU_MIN256 || |
379 | ifr->ifr_mtuifr_ifru.ifru_metric > MPE_MTU_MAX8192) |
380 | error = EINVAL22; |
381 | else |
382 | ifp->if_mtuif_data.ifi_mtu = ifr->ifr_mtuifr_ifru.ifru_metric; |
383 | break; |
384 | case SIOCGETLABEL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((154))): |
385 | shim.shim_label = MPLS_SHIM2LABEL(sc->sc_smpls.smpls_label)((__uint32_t)(__builtin_constant_p((sc->sc_smpls.smpls_label )) ? (__uint32_t)(((__uint32_t)((sc->sc_smpls.smpls_label) ) & 0xff) << 24 | ((__uint32_t)((sc->sc_smpls.smpls_label )) & 0xff00) << 8 | ((__uint32_t)((sc->sc_smpls. smpls_label)) & 0xff0000) >> 8 | ((__uint32_t)((sc-> sc_smpls.smpls_label)) & 0xff000000) >> 24) : __swap32md ((sc->sc_smpls.smpls_label))) >> 12); |
386 | if (shim.shim_label == 0) { |
387 | error = EADDRNOTAVAIL49; |
388 | break; |
389 | } |
390 | error = copyout(&shim, ifr->ifr_dataifr_ifru.ifru_data, sizeof(shim)); |
391 | break; |
392 | case SIOCSETLABEL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((153))): |
393 | error = copyin(ifr->ifr_dataifr_ifru.ifru_data, &shim, sizeof(shim)); |
394 | if (error != 0) |
395 | break; |
396 | if (shim.shim_label > MPLS_LABEL_MAX((1 << 20) - 1) || |
397 | shim.shim_label <= MPLS_LABEL_RESERVED_MAX15) { |
398 | error = EINVAL22; |
399 | break; |
400 | } |
401 | shim.shim_label = MPLS_LABEL2SHIM(shim.shim_label)((__uint32_t)(__builtin_constant_p((shim.shim_label) << 12) ? (__uint32_t)(((__uint32_t)((shim.shim_label) << 12 ) & 0xff) << 24 | ((__uint32_t)((shim.shim_label) << 12) & 0xff00) << 8 | ((__uint32_t)((shim.shim_label ) << 12) & 0xff0000) >> 8 | ((__uint32_t)((shim .shim_label) << 12) & 0xff000000) >> 24) : __swap32md ((shim.shim_label) << 12))); |
402 | if (sc->sc_smpls.smpls_label != shim.shim_label) { |
403 | error = mpe_set_label(sc, shim.shim_label, |
404 | sc->sc_rdomain); |
405 | } |
406 | break; |
407 | case SIOCDELLABEL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((151))): |
408 | if (sc->sc_smpls.smpls_label != MPLS_LABEL2SHIM(0)((__uint32_t)(__builtin_constant_p((0) << 12) ? (__uint32_t )(((__uint32_t)((0) << 12) & 0xff) << 24 | (( __uint32_t)((0) << 12) & 0xff00) << 8 | ((__uint32_t )((0) << 12) & 0xff0000) >> 8 | ((__uint32_t) ((0) << 12) & 0xff000000) >> 24) : __swap32md ((0) << 12)))) { |
409 | rt_ifa_del(&sc->sc_ifa, RTF_MPLS0x100000|RTF_LOCAL0x200000, |
410 | smplstosa(&sc->sc_smpls)((struct sockaddr *)(&sc->sc_smpls)), sc->sc_rdomain); |
411 | } |
412 | sc->sc_smpls.smpls_label = MPLS_LABEL2SHIM(0)((__uint32_t)(__builtin_constant_p((0) << 12) ? (__uint32_t )(((__uint32_t)((0) << 12) & 0xff) << 24 | (( __uint32_t)((0) << 12) & 0xff00) << 8 | ((__uint32_t )((0) << 12) & 0xff0000) >> 8 | ((__uint32_t) ((0) << 12) & 0xff000000) >> 24) : __swap32md ((0) << 12))); |
413 | break; |
414 | |
415 | case SIOCSLIFPHYRTABLE((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((161))): |
416 | if (ifr->ifr_rdomainidifr_ifru.ifru_metric < 0 || |
417 | ifr->ifr_rdomainidifr_ifru.ifru_metric > RT_TABLEID_MAX255 || |
418 | !rtable_exists(ifr->ifr_rdomainidifr_ifru.ifru_metric) || |
419 | ifr->ifr_rdomainidifr_ifru.ifru_metric != rtable_l2(ifr->ifr_rdomainidifr_ifru.ifru_metric)) { |
420 | error = EINVAL22; |
421 | break; |
422 | } |
423 | if (sc->sc_rdomain != ifr->ifr_rdomainidifr_ifru.ifru_metric) { |
424 | error = mpe_set_label(sc, sc->sc_smpls.smpls_label, |
425 | ifr->ifr_rdomainidifr_ifru.ifru_metric); |
426 | } |
427 | break; |
428 | case SIOCGLIFPHYRTABLE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((162))): |
429 | ifr->ifr_rdomainidifr_ifru.ifru_metric = sc->sc_rdomain; |
430 | break; |
431 | |
432 | case SIOCSTXHPRIO((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((197))): |
433 | error = if_txhprio_l3_check(ifr->ifr_hdrprioifr_ifru.ifru_metric); |
434 | if (error != 0) |
435 | break; |
436 | |
437 | sc->sc_txhprio = ifr->ifr_hdrprioifr_ifru.ifru_metric; |
438 | break; |
439 | case SIOCGTXHPRIO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((198))): |
440 | ifr->ifr_hdrprioifr_ifru.ifru_metric = sc->sc_txhprio; |
441 | break; |
442 | |
443 | case SIOCSRXHPRIO((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((219))): |
444 | error = if_rxhprio_l3_check(ifr->ifr_hdrprioifr_ifru.ifru_metric); |
445 | if (error != 0) |
446 | break; |
447 | |
448 | sc->sc_rxhprio = ifr->ifr_hdrprioifr_ifru.ifru_metric; |
449 | break; |
450 | case SIOCGRXHPRIO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((219))): |
451 | ifr->ifr_hdrprioifr_ifru.ifru_metric = sc->sc_rxhprio; |
452 | break; |
453 | |
454 | default: |
455 | return (ENOTTY25); |
456 | } |
457 | |
458 | return (error); |
459 | } |
460 | |
461 | void |
462 | mpe_input(struct ifnet *ifp, struct mbuf *m) |
463 | { |
464 | struct mpe_softc *sc = ifp->if_softc; |
465 | struct shim_hdr *shim; |
466 | struct mbuf *n; |
467 | uint8_t ttl, tos; |
468 | uint32_t exp; |
469 | int rxprio = sc->sc_rxhprio; |
470 | |
471 | shim = mtod(m, struct shim_hdr *)((struct shim_hdr *)((m)->m_hdr.mh_data)); |
472 | exp = ntohl(shim->shim_label & MPLS_EXP_MASK)(__uint32_t)(__builtin_constant_p(shim->shim_label & ( (u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t)(0x00000e00U )) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x00000e00U)) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x00000e00U)) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x00000e00U)) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x00000e00U ))))) ? (__uint32_t)(((__uint32_t)(shim->shim_label & ( (u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t)(0x00000e00U )) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x00000e00U)) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x00000e00U)) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x00000e00U)) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x00000e00U ))))) & 0xff) << 24 | ((__uint32_t)(shim->shim_label & ((u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t )(0x00000e00U)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x00000e00U ))))) & 0xff00) << 8 | ((__uint32_t)(shim->shim_label & ((u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t )(0x00000e00U)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x00000e00U ))))) & 0xff0000) >> 8 | ((__uint32_t)(shim->shim_label & ((u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t )(0x00000e00U)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x00000e00U ))))) & 0xff000000) >> 24) : __swap32md(shim->shim_label & ((u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t )(0x00000e00U)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x00000e00U )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x00000e00U )))))) >> MPLS_EXP_OFFSET9; |
473 | if (!MPLS_BOS_ISSET(shim->shim_label)(((shim->shim_label) & ((u_int32_t)(__uint32_t)(__builtin_constant_p ((u_int32_t)(0x00000100U)) ? (__uint32_t)(((__uint32_t)((u_int32_t )(0x00000100U)) & 0xff) << 24 | ((__uint32_t)((u_int32_t )(0x00000100U)) & 0xff00) << 8 | ((__uint32_t)((u_int32_t )(0x00000100U)) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t )(0x00000100U)) & 0xff000000) >> 24) : __swap32md(( u_int32_t)(0x00000100U))))) == ((u_int32_t)(__uint32_t)(__builtin_constant_p ((u_int32_t)(0x00000100U)) ? (__uint32_t)(((__uint32_t)((u_int32_t )(0x00000100U)) & 0xff) << 24 | ((__uint32_t)((u_int32_t )(0x00000100U)) & 0xff00) << 8 | ((__uint32_t)((u_int32_t )(0x00000100U)) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t )(0x00000100U)) & 0xff000000) >> 24) : __swap32md(( u_int32_t)(0x00000100U)))))) |
474 | goto drop; |
475 | |
476 | ttl = ntohl(shim->shim_label & MPLS_TTL_MASK)(__uint32_t)(__builtin_constant_p(shim->shim_label & ( (u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t)(0x000000ffU )) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x000000ffU)) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x000000ffU)) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x000000ffU)) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x000000ffU ))))) ? (__uint32_t)(((__uint32_t)(shim->shim_label & ( (u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t)(0x000000ffU )) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x000000ffU)) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x000000ffU)) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x000000ffU)) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x000000ffU ))))) & 0xff) << 24 | ((__uint32_t)(shim->shim_label & ((u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t )(0x000000ffU)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x000000ffU ))))) & 0xff00) << 8 | ((__uint32_t)(shim->shim_label & ((u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t )(0x000000ffU)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x000000ffU ))))) & 0xff0000) >> 8 | ((__uint32_t)(shim->shim_label & ((u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t )(0x000000ffU)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x000000ffU ))))) & 0xff000000) >> 24) : __swap32md(shim->shim_label & ((u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t )(0x000000ffU)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x000000ffU )) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x000000ffU )))))); |
477 | m_adj(m, sizeof(*shim)); |
478 | |
479 | n = m; |
480 | while (n->m_lenm_hdr.mh_len == 0) { |
481 | n = n->m_nextm_hdr.mh_next; |
482 | if (n == NULL((void *)0)) |
483 | goto drop; |
484 | } |
485 | |
486 | switch (*mtod(n, uint8_t *)((uint8_t *)((n)->m_hdr.mh_data)) >> 4) { |
487 | case 4: { |
488 | struct ip *ip; |
489 | if (m->m_lenm_hdr.mh_len < sizeof(*ip)) { |
490 | m = m_pullup(m, sizeof(*ip)); |
491 | if (m == NULL((void *)0)) |
492 | return; |
493 | } |
494 | ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data)); |
495 | tos = ip->ip_tos; |
496 | |
497 | if (mpls_mapttl_ip) { |
498 | m = mpls_ip_adjttl(m, ttl); |
499 | if (m == NULL((void *)0)) |
500 | return; |
501 | } |
502 | |
503 | m->m_pkthdrM_dat.MH.MH_pkthdr.ph_family = AF_INET2; |
504 | break; |
505 | } |
506 | #ifdef INET61 |
507 | case 6: { |
508 | struct ip6_hdr *ip6; |
509 | uint32_t flow; |
510 | if (m->m_lenm_hdr.mh_len < sizeof(*ip6)) { |
511 | m = m_pullup(m, sizeof(*ip6)); |
512 | if (m == NULL((void *)0)) |
513 | return; |
514 | } |
515 | ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data)); |
516 | flow = bemtoh32(&ip6->ip6_flow)(__uint32_t)(__builtin_constant_p(*(__uint32_t *)(&ip6-> ip6_ctlun.ip6_un1.ip6_un1_flow)) ? (__uint32_t)(((__uint32_t) (*(__uint32_t *)(&ip6->ip6_ctlun.ip6_un1.ip6_un1_flow) ) & 0xff) << 24 | ((__uint32_t)(*(__uint32_t *)(& ip6->ip6_ctlun.ip6_un1.ip6_un1_flow)) & 0xff00) << 8 | ((__uint32_t)(*(__uint32_t *)(&ip6->ip6_ctlun.ip6_un1 .ip6_un1_flow)) & 0xff0000) >> 8 | ((__uint32_t)(*( __uint32_t *)(&ip6->ip6_ctlun.ip6_un1.ip6_un1_flow)) & 0xff000000) >> 24) : __swap32md(*(__uint32_t *)(&ip6 ->ip6_ctlun.ip6_un1.ip6_un1_flow))); |
517 | tos = flow >> 20; |
518 | |
519 | if (mpls_mapttl_ip6) { |
520 | m = mpls_ip6_adjttl(m, ttl); |
521 | if (m == NULL((void *)0)) |
522 | return; |
523 | } |
524 | |
525 | m->m_pkthdrM_dat.MH.MH_pkthdr.ph_family = AF_INET624; |
526 | break; |
527 | } |
528 | #endif /* INET6 */ |
529 | default: |
530 | goto drop; |
531 | } |
532 | |
533 | switch (rxprio) { |
534 | case IF_HDRPRIO_PACKET-1: |
535 | /* nop */ |
536 | break; |
537 | case IF_HDRPRIO_OUTER-3: |
538 | m->m_pkthdrM_dat.MH.MH_pkthdr.pf.prio = exp; |
539 | break; |
540 | case IF_HDRPRIO_PAYLOAD-2: |
541 | m->m_pkthdrM_dat.MH.MH_pkthdr.pf.prio = IFQ_TOS2PRIO(tos)((tos) >> 5); |
542 | break; |
543 | default: |
544 | m->m_pkthdrM_dat.MH.MH_pkthdr.pf.prio = rxprio; |
545 | break; |
546 | } |
547 | |
548 | if_vinput(ifp, m); |
549 | return; |
550 | drop: |
551 | m_freem(m); |
552 | } |