1 1.41 ozaki /* $NetBSD: link_proto.c,v 1.41 2025/06/05 06:29:27 ozaki-r Exp $ */ 2 1.1 dyoung 3 1.1 dyoung /*- 4 1.1 dyoung * Copyright (c) 1982, 1986, 1993 5 1.1 dyoung * The Regents of the University of California. All rights reserved. 6 1.1 dyoung * 7 1.1 dyoung * Redistribution and use in source and binary forms, with or without 8 1.1 dyoung * modification, are permitted provided that the following conditions 9 1.1 dyoung * are met: 10 1.1 dyoung * 1. Redistributions of source code must retain the above copyright 11 1.1 dyoung * notice, this list of conditions and the following disclaimer. 12 1.1 dyoung * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 dyoung * notice, this list of conditions and the following disclaimer in the 14 1.1 dyoung * documentation and/or other materials provided with the distribution. 15 1.1 dyoung * 3. Neither the name of the University nor the names of its contributors 16 1.1 dyoung * may be used to endorse or promote products derived from this software 17 1.1 dyoung * without specific prior written permission. 18 1.1 dyoung * 19 1.1 dyoung * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 dyoung * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 dyoung * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 dyoung * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 dyoung * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 dyoung * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 dyoung * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 dyoung * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 dyoung * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 dyoung * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 dyoung * SUCH DAMAGE. 30 1.1 dyoung * 31 1.1 dyoung * @(#)uipc_proto.c 8.2 (Berkeley) 2/14/95 32 1.1 dyoung */ 33 1.1 dyoung 34 1.1 dyoung #include <sys/cdefs.h> 35 1.41 ozaki __KERNEL_RCSID(0, "$NetBSD: link_proto.c,v 1.41 2025/06/05 06:29:27 ozaki-r Exp $"); 36 1.1 dyoung 37 1.1 dyoung #include <sys/param.h> 38 1.1 dyoung #include <sys/socket.h> 39 1.1 dyoung #include <sys/protosw.h> 40 1.1 dyoung #include <sys/domain.h> 41 1.1 dyoung #include <sys/mbuf.h> 42 1.1 dyoung #include <sys/un.h> 43 1.1 dyoung #include <sys/socketvar.h> 44 1.1 dyoung 45 1.1 dyoung #include <net/if.h> 46 1.1 dyoung #include <net/if_dl.h> 47 1.1 dyoung #include <net/raw_cb.h> 48 1.4 dyoung #include <net/route.h> 49 1.1 dyoung 50 1.1 dyoung static int sockaddr_dl_cmp(const struct sockaddr *, const struct sockaddr *); 51 1.9 rmind static int link_attach(struct socket *, int); 52 1.9 rmind static void link_detach(struct socket *); 53 1.26 rtr static int link_accept(struct socket *, struct sockaddr *); 54 1.25 rtr static int link_bind(struct socket *, struct sockaddr *, struct lwp *); 55 1.21 rtr static int link_listen(struct socket *, struct lwp *); 56 1.28 rtr static int link_connect(struct socket *, struct sockaddr *, struct lwp *); 57 1.24 rtr static int link_connect2(struct socket *, struct socket *); 58 1.19 rtr static int link_disconnect(struct socket *); 59 1.19 rtr static int link_shutdown(struct socket *); 60 1.19 rtr static int link_abort(struct socket *); 61 1.12 rtr static int link_ioctl(struct socket *, u_long, void *, struct ifnet *); 62 1.13 rtr static int link_stat(struct socket *, struct stat *); 63 1.26 rtr static int link_peeraddr(struct socket *, struct sockaddr *); 64 1.26 rtr static int link_sockaddr(struct socket *, struct sockaddr *); 65 1.23 rtr static int link_rcvd(struct socket *, int, struct lwp *); 66 1.20 rtr static int link_recvoob(struct socket *, struct mbuf *, int); 67 1.28 rtr static int link_send(struct socket *, struct mbuf *, struct sockaddr *, 68 1.22 rtr struct mbuf *, struct lwp *); 69 1.20 rtr static int link_sendoob(struct socket *, struct mbuf *, struct mbuf *); 70 1.24 rtr static int link_purgeif(struct socket *, struct ifnet *); 71 1.4 dyoung static void link_init(void); 72 1.1 dyoung 73 1.1 dyoung /* 74 1.1 dyoung * Definitions of protocols supported in the link-layer domain. 75 1.1 dyoung */ 76 1.1 dyoung 77 1.1 dyoung DOMAIN_DEFINE(linkdomain); /* forward define and add to link set */ 78 1.1 dyoung 79 1.8 rmind static const struct pr_usrreqs link_usrreqs = { 80 1.9 rmind .pr_attach = link_attach, 81 1.9 rmind .pr_detach = link_detach, 82 1.18 rtr .pr_accept = link_accept, 83 1.18 rtr .pr_bind = link_bind, 84 1.18 rtr .pr_listen = link_listen, 85 1.20 rtr .pr_connect = link_connect, 86 1.24 rtr .pr_connect2 = link_connect2, 87 1.19 rtr .pr_disconnect = link_disconnect, 88 1.19 rtr .pr_shutdown = link_shutdown, 89 1.19 rtr .pr_abort = link_abort, 90 1.10 rtr .pr_ioctl = link_ioctl, 91 1.13 rtr .pr_stat = link_stat, 92 1.15 rtr .pr_peeraddr = link_peeraddr, 93 1.15 rtr .pr_sockaddr = link_sockaddr, 94 1.23 rtr .pr_rcvd = link_rcvd, 95 1.20 rtr .pr_recvoob = link_recvoob, 96 1.22 rtr .pr_send = link_send, 97 1.20 rtr .pr_sendoob = link_sendoob, 98 1.24 rtr .pr_purgeif = link_purgeif, 99 1.8 rmind }; 100 1.8 rmind 101 1.30 riastrad const struct protosw linksw[] = { 102 1.4 dyoung { .pr_type = SOCK_DGRAM, 103 1.4 dyoung .pr_domain = &linkdomain, 104 1.4 dyoung .pr_protocol = 0, /* XXX */ 105 1.4 dyoung .pr_flags = PR_ATOMIC|PR_ADDR|PR_PURGEIF, 106 1.4 dyoung .pr_input = NULL, 107 1.4 dyoung .pr_ctlinput = NULL, 108 1.4 dyoung .pr_ctloutput = NULL, 109 1.8 rmind .pr_usrreqs = &link_usrreqs, 110 1.4 dyoung .pr_init = link_init, 111 1.4 dyoung }, 112 1.4 dyoung }; 113 1.4 dyoung 114 1.1 dyoung struct domain linkdomain = { 115 1.1 dyoung .dom_family = AF_LINK, 116 1.1 dyoung .dom_name = "link", 117 1.1 dyoung .dom_externalize = NULL, 118 1.1 dyoung .dom_dispose = NULL, 119 1.4 dyoung .dom_protosw = linksw, 120 1.30 riastrad .dom_protoswNPROTOSW = &linksw[__arraycount(linksw)], 121 1.1 dyoung .dom_sockaddr_cmp = sockaddr_dl_cmp 122 1.1 dyoung }; 123 1.1 dyoung 124 1.4 dyoung static void 125 1.4 dyoung link_init(void) 126 1.4 dyoung { 127 1.4 dyoung return; 128 1.4 dyoung } 129 1.4 dyoung 130 1.4 dyoung static int 131 1.4 dyoung link_control(struct socket *so, unsigned long cmd, void *data, 132 1.12 rtr struct ifnet *ifp) 133 1.4 dyoung { 134 1.4 dyoung int error, s; 135 1.4 dyoung bool isactive, mkactive; 136 1.4 dyoung struct if_laddrreq *iflr; 137 1.4 dyoung union { 138 1.4 dyoung struct sockaddr sa; 139 1.4 dyoung struct sockaddr_dl sdl; 140 1.4 dyoung struct sockaddr_storage ss; 141 1.4 dyoung } u; 142 1.4 dyoung struct ifaddr *ifa; 143 1.4 dyoung const struct sockaddr_dl *asdl, *nsdl; 144 1.33 ozaki struct psref psref; 145 1.4 dyoung 146 1.4 dyoung switch (cmd) { 147 1.4 dyoung case SIOCALIFADDR: 148 1.4 dyoung case SIOCDLIFADDR: 149 1.4 dyoung case SIOCGLIFADDR: 150 1.4 dyoung iflr = data; 151 1.4 dyoung 152 1.4 dyoung if (iflr->addr.ss_family != AF_LINK) 153 1.4 dyoung return EINVAL; 154 1.4 dyoung 155 1.4 dyoung asdl = satocsdl(sstocsa(&iflr->addr)); 156 1.4 dyoung 157 1.4 dyoung if (asdl->sdl_alen != ifp->if_addrlen) 158 1.4 dyoung return EINVAL; 159 1.4 dyoung 160 1.4 dyoung if (sockaddr_dl_init(&u.sdl, sizeof(u.ss), ifp->if_index, 161 1.4 dyoung ifp->if_type, ifp->if_xname, strlen(ifp->if_xname), 162 1.4 dyoung CLLADDR(asdl), asdl->sdl_alen) == NULL) 163 1.4 dyoung return EINVAL; 164 1.4 dyoung 165 1.4 dyoung if ((iflr->flags & IFLR_PREFIX) == 0) 166 1.4 dyoung ; 167 1.4 dyoung else if (iflr->prefixlen != NBBY * ifp->if_addrlen) 168 1.4 dyoung return EINVAL; /* XXX match with prefix */ 169 1.4 dyoung 170 1.4 dyoung error = 0; 171 1.4 dyoung 172 1.33 ozaki s = pserialize_read_enter(); 173 1.31 ozaki IFADDR_READER_FOREACH(ifa, ifp) { 174 1.33 ozaki if (sockaddr_cmp(&u.sa, ifa->ifa_addr) == 0) { 175 1.33 ozaki ifa_acquire(ifa, &psref); 176 1.4 dyoung break; 177 1.33 ozaki } 178 1.4 dyoung } 179 1.33 ozaki pserialize_read_exit(s); 180 1.4 dyoung 181 1.4 dyoung switch (cmd) { 182 1.4 dyoung case SIOCGLIFADDR: 183 1.33 ozaki ifa_release(ifa, &psref); 184 1.33 ozaki s = pserialize_read_enter(); 185 1.41 ozaki if ((iflr->flags & IFLR_PREFIX) == 0) 186 1.41 ozaki ifa = if_first_addr(ifp, AF_LINK); 187 1.4 dyoung if (ifa == NULL) { 188 1.33 ozaki pserialize_read_exit(s); 189 1.7 dyoung error = EADDRNOTAVAIL; 190 1.4 dyoung break; 191 1.4 dyoung } 192 1.4 dyoung 193 1.4 dyoung if (ifa == ifp->if_dl) 194 1.4 dyoung iflr->flags = IFLR_ACTIVE; 195 1.4 dyoung else 196 1.4 dyoung iflr->flags = 0; 197 1.4 dyoung 198 1.5 dyoung if (ifa == ifp->if_hwdl) 199 1.5 dyoung iflr->flags |= IFLR_FACTORY; 200 1.5 dyoung 201 1.4 dyoung sockaddr_copy(sstosa(&iflr->addr), sizeof(iflr->addr), 202 1.4 dyoung ifa->ifa_addr); 203 1.33 ozaki pserialize_read_exit(s); 204 1.33 ozaki ifa = NULL; 205 1.4 dyoung 206 1.4 dyoung break; 207 1.4 dyoung case SIOCDLIFADDR: 208 1.4 dyoung if (ifa == NULL) 209 1.4 dyoung error = EADDRNOTAVAIL; 210 1.5 dyoung else if (ifa == ifp->if_dl || ifa == ifp->if_hwdl) 211 1.4 dyoung error = EBUSY; 212 1.4 dyoung else { 213 1.4 dyoung /* TBD routing socket */ 214 1.38 roy rt_addrmsg(RTM_DELETE, ifa); 215 1.34 ozaki /* We need to release psref for ifa_remove */ 216 1.34 ozaki ifaref(ifa); 217 1.34 ozaki ifa_release(ifa, &psref); 218 1.4 dyoung ifa_remove(ifp, ifa); 219 1.39 ozaki KASSERTMSG(ifa->ifa_refcnt == 1, "ifa_refcnt=%d", 220 1.39 ozaki ifa->ifa_refcnt); 221 1.34 ozaki ifafree(ifa); 222 1.34 ozaki ifa = NULL; 223 1.4 dyoung } 224 1.4 dyoung break; 225 1.4 dyoung case SIOCALIFADDR: 226 1.33 ozaki if (ifa == NULL) { 227 1.33 ozaki ifa = if_dl_create(ifp, &nsdl); 228 1.33 ozaki if (ifa == NULL) { 229 1.33 ozaki error = ENOMEM; 230 1.33 ozaki break; 231 1.33 ozaki } 232 1.33 ozaki ifa_acquire(ifa, &psref); 233 1.4 dyoung sockaddr_copy(ifa->ifa_addr, 234 1.4 dyoung ifa->ifa_addr->sa_len, &u.sa); 235 1.4 dyoung ifa_insert(ifp, ifa); 236 1.38 roy rt_addrmsg(RTM_ADD, ifa); 237 1.4 dyoung } 238 1.4 dyoung 239 1.4 dyoung mkactive = (iflr->flags & IFLR_ACTIVE) != 0; 240 1.4 dyoung isactive = (ifa == ifp->if_dl); 241 1.4 dyoung 242 1.4 dyoung if (!isactive && mkactive) { 243 1.4 dyoung if_activate_sadl(ifp, ifa, nsdl); 244 1.38 roy rt_addrmsg(RTM_CHANGE, ifa); 245 1.4 dyoung error = ENETRESET; 246 1.4 dyoung } 247 1.4 dyoung break; 248 1.4 dyoung } 249 1.33 ozaki ifa_release(ifa, &psref); 250 1.4 dyoung if (error != ENETRESET) 251 1.4 dyoung return error; 252 1.17 ozaki else if ((ifp->if_flags & IFF_RUNNING) != 0 && 253 1.17 ozaki ifp->if_init != NULL) 254 1.40 riastrad return if_init(ifp); 255 1.4 dyoung else 256 1.4 dyoung return 0; 257 1.4 dyoung default: 258 1.4 dyoung return ENOTTY; 259 1.4 dyoung } 260 1.4 dyoung } 261 1.4 dyoung 262 1.4 dyoung static int 263 1.9 rmind link_attach(struct socket *so, int proto) 264 1.9 rmind { 265 1.9 rmind sosetlock(so); 266 1.9 rmind KASSERT(solocked(so)); 267 1.9 rmind return 0; 268 1.9 rmind } 269 1.9 rmind 270 1.9 rmind static void 271 1.9 rmind link_detach(struct socket *so) 272 1.9 rmind { 273 1.9 rmind KASSERT(solocked(so)); 274 1.9 rmind sofree(so); 275 1.9 rmind } 276 1.9 rmind 277 1.9 rmind static int 278 1.26 rtr link_accept(struct socket *so, struct sockaddr *nam) 279 1.18 rtr { 280 1.18 rtr KASSERT(solocked(so)); 281 1.18 rtr 282 1.18 rtr return EOPNOTSUPP; 283 1.18 rtr } 284 1.18 rtr 285 1.18 rtr static int 286 1.25 rtr link_bind(struct socket *so, struct sockaddr *nam, struct lwp *l) 287 1.18 rtr { 288 1.18 rtr KASSERT(solocked(so)); 289 1.18 rtr 290 1.18 rtr return EOPNOTSUPP; 291 1.18 rtr } 292 1.18 rtr 293 1.18 rtr static int 294 1.21 rtr link_listen(struct socket *so, struct lwp *l) 295 1.18 rtr { 296 1.18 rtr KASSERT(solocked(so)); 297 1.18 rtr 298 1.18 rtr return EOPNOTSUPP; 299 1.18 rtr } 300 1.18 rtr 301 1.18 rtr static int 302 1.28 rtr link_connect(struct socket *so, struct sockaddr *nam, struct lwp *l) 303 1.20 rtr { 304 1.20 rtr KASSERT(solocked(so)); 305 1.20 rtr 306 1.20 rtr return EOPNOTSUPP; 307 1.20 rtr } 308 1.20 rtr 309 1.20 rtr static int 310 1.24 rtr link_connect2(struct socket *so, struct socket *so2) 311 1.24 rtr { 312 1.24 rtr KASSERT(solocked(so)); 313 1.24 rtr 314 1.24 rtr return EOPNOTSUPP; 315 1.24 rtr } 316 1.24 rtr 317 1.24 rtr static int 318 1.19 rtr link_disconnect(struct socket *so) 319 1.19 rtr { 320 1.19 rtr KASSERT(solocked(so)); 321 1.19 rtr 322 1.19 rtr return EOPNOTSUPP; 323 1.19 rtr } 324 1.19 rtr 325 1.19 rtr static int 326 1.19 rtr link_shutdown(struct socket *so) 327 1.19 rtr { 328 1.19 rtr KASSERT(solocked(so)); 329 1.19 rtr 330 1.19 rtr return EOPNOTSUPP; 331 1.19 rtr } 332 1.19 rtr 333 1.19 rtr static int 334 1.19 rtr link_abort(struct socket *so) 335 1.19 rtr { 336 1.19 rtr KASSERT(solocked(so)); 337 1.19 rtr 338 1.19 rtr return EOPNOTSUPP; 339 1.19 rtr } 340 1.19 rtr 341 1.19 rtr static int 342 1.12 rtr link_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) 343 1.10 rtr { 344 1.12 rtr return link_control(so, cmd, nam, ifp); 345 1.10 rtr } 346 1.10 rtr 347 1.10 rtr static int 348 1.13 rtr link_stat(struct socket *so, struct stat *ub) 349 1.13 rtr { 350 1.14 rtr KASSERT(solocked(so)); 351 1.14 rtr 352 1.32 njoly return 0; 353 1.13 rtr } 354 1.13 rtr 355 1.13 rtr static int 356 1.26 rtr link_peeraddr(struct socket *so, struct sockaddr *nam) 357 1.15 rtr { 358 1.15 rtr KASSERT(solocked(so)); 359 1.15 rtr 360 1.15 rtr return EOPNOTSUPP; 361 1.15 rtr } 362 1.15 rtr 363 1.15 rtr static int 364 1.26 rtr link_sockaddr(struct socket *so, struct sockaddr *nam) 365 1.15 rtr { 366 1.15 rtr KASSERT(solocked(so)); 367 1.15 rtr 368 1.15 rtr return EOPNOTSUPP; 369 1.15 rtr } 370 1.15 rtr 371 1.15 rtr static int 372 1.23 rtr link_rcvd(struct socket *so, int flags, struct lwp *l) 373 1.23 rtr { 374 1.23 rtr KASSERT(solocked(so)); 375 1.23 rtr 376 1.23 rtr return EOPNOTSUPP; 377 1.23 rtr } 378 1.23 rtr 379 1.23 rtr static int 380 1.20 rtr link_recvoob(struct socket *so, struct mbuf *m, int flags) 381 1.20 rtr { 382 1.20 rtr KASSERT(solocked(so)); 383 1.20 rtr 384 1.20 rtr return EOPNOTSUPP; 385 1.20 rtr } 386 1.20 rtr 387 1.20 rtr static int 388 1.28 rtr link_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, 389 1.22 rtr struct mbuf *control, struct lwp *l) 390 1.22 rtr { 391 1.22 rtr KASSERT(solocked(so)); 392 1.22 rtr 393 1.22 rtr return EOPNOTSUPP; 394 1.22 rtr } 395 1.22 rtr 396 1.22 rtr static int 397 1.20 rtr link_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) 398 1.20 rtr { 399 1.20 rtr KASSERT(solocked(so)); 400 1.20 rtr 401 1.37 martin m_freem(m); 402 1.37 martin m_freem(control); 403 1.37 martin 404 1.20 rtr return EOPNOTSUPP; 405 1.20 rtr } 406 1.20 rtr 407 1.20 rtr static int 408 1.24 rtr link_purgeif(struct socket *so, struct ifnet *ifp) 409 1.24 rtr { 410 1.24 rtr 411 1.24 rtr return EOPNOTSUPP; 412 1.24 rtr } 413 1.24 rtr 414 1.1 dyoung /* Compare the field at byte offsets [fieldstart, fieldend) in 415 1.1 dyoung * two memory regions, [l, l + llen) and [r, r + llen). 416 1.1 dyoung */ 417 1.1 dyoung static inline int 418 1.1 dyoung submemcmp(const void *l, const void *r, 419 1.1 dyoung const uint_fast8_t llen, const uint_fast8_t rlen, 420 1.1 dyoung const uint_fast8_t fieldstart, const uint_fast8_t fieldend) 421 1.1 dyoung { 422 1.1 dyoung uint_fast8_t cmpend, minlen; 423 1.1 dyoung const uint8_t *lb = l, *rb = r; 424 1.1 dyoung int rc; 425 1.1 dyoung 426 1.1 dyoung minlen = MIN(llen, rlen); 427 1.1 dyoung 428 1.1 dyoung /* The field is missing from one region. The shorter region is the 429 1.1 dyoung * lesser region. 430 1.1 dyoung */ 431 1.1 dyoung if (fieldstart >= minlen) 432 1.1 dyoung return llen - rlen; 433 1.1 dyoung 434 1.1 dyoung /* Two empty, present fields are always equal. */ 435 1.1 dyoung if (fieldstart > fieldend) 436 1.1 dyoung return 0; 437 1.1 dyoung 438 1.1 dyoung cmpend = MIN(fieldend, minlen); 439 1.1 dyoung 440 1.1 dyoung rc = memcmp(&lb[fieldstart], &rb[fieldstart], cmpend - fieldstart); 441 1.1 dyoung 442 1.1 dyoung if (rc != 0) 443 1.1 dyoung return rc; 444 1.1 dyoung /* If one or both fields are truncated, then the shorter is the lesser 445 1.1 dyoung * field. 446 1.1 dyoung */ 447 1.1 dyoung if (minlen < fieldend) 448 1.1 dyoung return llen - rlen; 449 1.1 dyoung /* Fields are full-length and equal. The fields are equal. */ 450 1.1 dyoung return 0; 451 1.1 dyoung } 452 1.1 dyoung 453 1.2 dyoung uint8_t 454 1.2 dyoung sockaddr_dl_measure(uint8_t namelen, uint8_t addrlen) 455 1.2 dyoung { 456 1.2 dyoung return offsetof(struct sockaddr_dl, sdl_data[namelen + addrlen]); 457 1.2 dyoung } 458 1.2 dyoung 459 1.3 dyoung struct sockaddr * 460 1.3 dyoung sockaddr_dl_alloc(uint16_t ifindex, uint8_t type, 461 1.3 dyoung const void *name, uint8_t namelen, const void *addr, uint8_t addrlen, 462 1.3 dyoung int flags) 463 1.3 dyoung { 464 1.3 dyoung struct sockaddr *sa; 465 1.3 dyoung socklen_t len; 466 1.3 dyoung 467 1.3 dyoung len = sockaddr_dl_measure(namelen, addrlen); 468 1.3 dyoung sa = sockaddr_alloc(AF_LINK, len, flags); 469 1.3 dyoung 470 1.3 dyoung if (sa == NULL) 471 1.3 dyoung return NULL; 472 1.3 dyoung 473 1.3 dyoung if (sockaddr_dl_init(satosdl(sa), len, ifindex, type, name, namelen, 474 1.3 dyoung addr, addrlen) == NULL) { 475 1.3 dyoung sockaddr_free(sa); 476 1.3 dyoung return NULL; 477 1.3 dyoung } 478 1.3 dyoung 479 1.3 dyoung return sa; 480 1.3 dyoung } 481 1.3 dyoung 482 1.3 dyoung struct sockaddr_dl * 483 1.3 dyoung sockaddr_dl_init(struct sockaddr_dl *sdl, socklen_t socklen, uint16_t ifindex, 484 1.3 dyoung uint8_t type, const void *name, uint8_t namelen, const void *addr, 485 1.3 dyoung uint8_t addrlen) 486 1.2 dyoung { 487 1.3 dyoung socklen_t len; 488 1.3 dyoung 489 1.2 dyoung sdl->sdl_family = AF_LINK; 490 1.2 dyoung sdl->sdl_slen = 0; 491 1.3 dyoung len = sockaddr_dl_measure(namelen, addrlen); 492 1.3 dyoung if (len > socklen) { 493 1.3 dyoung sdl->sdl_len = socklen; 494 1.3 dyoung #ifdef DIAGNOSTIC 495 1.16 joerg printf("%s: too long: %u > %u\n", __func__, (u_int)len, 496 1.16 joerg (u_int)socklen); 497 1.3 dyoung #endif 498 1.3 dyoung return NULL; 499 1.3 dyoung } 500 1.3 dyoung sdl->sdl_len = len; 501 1.2 dyoung sdl->sdl_index = ifindex; 502 1.2 dyoung sdl->sdl_type = type; 503 1.3 dyoung memset(&sdl->sdl_data[0], 0, namelen + addrlen); 504 1.3 dyoung if (name != NULL) { 505 1.2 dyoung memcpy(&sdl->sdl_data[0], name, namelen); 506 1.3 dyoung sdl->sdl_nlen = namelen; 507 1.3 dyoung } else 508 1.3 dyoung sdl->sdl_nlen = 0; 509 1.3 dyoung if (addr != NULL) { 510 1.2 dyoung memcpy(&sdl->sdl_data[sdl->sdl_nlen], addr, addrlen); 511 1.3 dyoung sdl->sdl_alen = addrlen; 512 1.3 dyoung } else 513 1.3 dyoung sdl->sdl_alen = 0; 514 1.3 dyoung return sdl; 515 1.2 dyoung } 516 1.2 dyoung 517 1.1 dyoung static int 518 1.1 dyoung sockaddr_dl_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2) 519 1.1 dyoung { 520 1.1 dyoung int rc; 521 1.1 dyoung const uint_fast8_t indexofs = offsetof(struct sockaddr_dl, sdl_index); 522 1.1 dyoung const uint_fast8_t nlenofs = offsetof(struct sockaddr_dl, sdl_nlen); 523 1.1 dyoung uint_fast8_t dataofs = offsetof(struct sockaddr_dl, sdl_data[0]); 524 1.1 dyoung const struct sockaddr_dl *sdl1, *sdl2; 525 1.1 dyoung 526 1.1 dyoung sdl1 = satocsdl(sa1); 527 1.1 dyoung sdl2 = satocsdl(sa2); 528 1.1 dyoung 529 1.1 dyoung rc = submemcmp(sdl1, sdl2, sdl1->sdl_len, sdl2->sdl_len, 530 1.1 dyoung indexofs, nlenofs); 531 1.1 dyoung 532 1.1 dyoung if (rc != 0) 533 1.1 dyoung return rc; 534 1.1 dyoung 535 1.1 dyoung rc = submemcmp(sdl1, sdl2, sdl1->sdl_len, sdl2->sdl_len, 536 1.1 dyoung dataofs, dataofs + MIN(sdl1->sdl_nlen, sdl2->sdl_nlen)); 537 1.1 dyoung 538 1.1 dyoung if (rc != 0) 539 1.1 dyoung return rc; 540 1.1 dyoung 541 1.1 dyoung if (sdl1->sdl_nlen != sdl2->sdl_nlen) 542 1.1 dyoung return sdl1->sdl_nlen - sdl2->sdl_nlen; 543 1.1 dyoung 544 1.1 dyoung dataofs += sdl1->sdl_nlen; 545 1.1 dyoung 546 1.1 dyoung rc = submemcmp(sdl1, sdl2, sdl1->sdl_len, sdl2->sdl_len, 547 1.1 dyoung dataofs, dataofs + MIN(sdl1->sdl_alen, sdl2->sdl_alen)); 548 1.1 dyoung 549 1.1 dyoung if (rc != 0) 550 1.1 dyoung return rc; 551 1.1 dyoung 552 1.1 dyoung if (sdl1->sdl_alen != sdl2->sdl_alen) 553 1.1 dyoung return sdl1->sdl_alen - sdl2->sdl_alen; 554 1.1 dyoung 555 1.1 dyoung dataofs += sdl1->sdl_alen; 556 1.1 dyoung 557 1.1 dyoung rc = submemcmp(sdl1, sdl2, sdl1->sdl_len, sdl2->sdl_len, 558 1.1 dyoung dataofs, dataofs + MIN(sdl1->sdl_slen, sdl2->sdl_slen)); 559 1.1 dyoung 560 1.1 dyoung if (sdl1->sdl_slen != sdl2->sdl_slen) 561 1.1 dyoung return sdl1->sdl_slen - sdl2->sdl_slen; 562 1.1 dyoung 563 1.1 dyoung return sdl1->sdl_len - sdl2->sdl_len; 564 1.1 dyoung } 565 1.2 dyoung 566 1.2 dyoung struct sockaddr_dl * 567 1.3 dyoung sockaddr_dl_setaddr(struct sockaddr_dl *sdl, socklen_t socklen, 568 1.3 dyoung const void *addr, uint8_t addrlen) 569 1.2 dyoung { 570 1.3 dyoung socklen_t len; 571 1.2 dyoung 572 1.3 dyoung len = sockaddr_dl_measure(sdl->sdl_nlen, addrlen); 573 1.3 dyoung if (len > socklen) { 574 1.3 dyoung #ifdef DIAGNOSTIC 575 1.16 joerg printf("%s: too long: %u > %u\n", __func__, (u_int)len, 576 1.16 joerg (u_int)socklen); 577 1.3 dyoung #endif 578 1.2 dyoung return NULL; 579 1.2 dyoung } 580 1.2 dyoung memcpy(&sdl->sdl_data[sdl->sdl_nlen], addr, addrlen); 581 1.2 dyoung sdl->sdl_alen = addrlen; 582 1.3 dyoung sdl->sdl_len = len; 583 1.2 dyoung return sdl; 584 1.2 dyoung } 585