1/* 2 * Copyright (c) 1990,1994 Regents of The University of Michigan. 3 * All Rights Reserved. See COPYRIGHT. 4 */ 5 6#include <sys/param.h> 7#include <sys/systm.h> 8#include <sys/proc.h> 9#include <sys/malloc.h> 10#include <sys/mbuf.h> 11#include <sys/socket.h> 12#include <sys/socketvar.h> 13#include <sys/protosw.h> 14#include <net/if.h> 15#include <net/route.h> 16 17#include <netatalk/at.h> 18#include <netatalk/at_var.h> 19#include <netatalk/ddp_var.h> 20#include <netatalk/at_extern.h> 21 22static void at_pcbdisconnect( struct ddpcb *ddp ); 23static void at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr); 24static int at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr, 25 struct proc *p); 26static int at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr, 27 struct proc *p); 28static void at_pcbdetach(struct socket *so, struct ddpcb *ddp); 29static int at_pcballoc(struct socket *so); 30 31struct ddpcb *ddp_ports[ ATPORT_LAST ]; 32struct ddpcb *ddpcb = NULL; 33static u_long ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */ 34static u_long ddp_recvspace = 10 * ( 587 + sizeof( struct sockaddr_at )); 35 36 37static int 38ddp_attach(struct socket *so, int proto, struct proc *p) 39{ 40 struct ddpcb *ddp; 41 int error = 0; 42 int s; 43 44 45 ddp = sotoddpcb( so ); 46 if ( ddp != NULL ) { 47 return( EINVAL); 48 } 49 50 s = splnet(); 51 error = at_pcballoc( so ); 52 splx(s); 53 if (error) { 54 return (error); 55 } 56 return (soreserve( so, ddp_sendspace, ddp_recvspace )); 57} 58 59static int 60ddp_detach(struct socket *so) 61{ 62 struct ddpcb *ddp; 63 int s; 64 65 ddp = sotoddpcb( so ); 66 if ( ddp == NULL ) { 67 return( EINVAL); 68 } 69 s = splnet(); 70 at_pcbdetach( so, ddp ); 71 splx(s); 72 return(0); 73} 74 75static int 76ddp_bind(struct socket *so, struct sockaddr *nam, struct proc *p) 77{ 78 struct ddpcb *ddp; 79 int error = 0; 80 int s; 81 82 ddp = sotoddpcb( so ); 83 if ( ddp == NULL ) { 84 return( EINVAL); 85 } 86 s = splnet(); 87 error = at_pcbsetaddr(ddp, nam, p); 88 splx(s); 89 return (error); 90} 91 92static int 93ddp_connect(struct socket *so, struct sockaddr *nam, struct proc *p) 94{ 95 struct ddpcb *ddp; 96 int error = 0; 97 int s; 98 99 ddp = sotoddpcb( so ); 100 if ( ddp == NULL ) { 101 return( EINVAL); 102 } 103 104 if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) { 105 return(EISCONN); 106 } 107 108 s = splnet(); 109 error = at_pcbconnect( ddp, nam, p ); 110 splx(s); 111 if ( error == 0 ) 112 soisconnected( so ); 113 return(error); 114} 115 116static int 117ddp_disconnect(struct socket *so) 118{ 119 120 struct ddpcb *ddp; 121 int s; 122 123 ddp = sotoddpcb( so ); 124 if ( ddp == NULL ) { 125 return( EINVAL); 126 } 127 if ( ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE ) { 128 return(ENOTCONN); 129 } 130 131 s = splnet(); 132 at_pcbdisconnect( ddp ); 133 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE; 134 splx(s); 135 soisdisconnected( so ); 136 return(0); 137} 138 139static int 140ddp_shutdown(struct socket *so) 141{ 142 struct ddpcb *ddp; 143 144 ddp = sotoddpcb( so ); 145 if ( ddp == NULL ) { 146 return( EINVAL); 147 } 148 socantsendmore( so ); 149 return(0); 150} 151 152static int 153ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, 154 struct mbuf *control, struct proc *p) 155{ 156 struct ddpcb *ddp; 157 int error = 0; 158 int s; 159 160 ddp = sotoddpcb( so ); 161 if ( ddp == NULL ) { 162 return(EINVAL); 163 } 164 165 if ( control && control->m_len ) { 166 return(EINVAL); 167 } 168 169 if ( addr ) { 170 if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) { 171 return(EISCONN); 172 } 173 174 s = splnet(); 175 error = at_pcbconnect(ddp, addr, p); 176 splx( s ); 177 if ( error ) { 178 return(error); 179 } 180 } else { 181 if ( ddp->ddp_fsat.sat_port == ATADDR_ANYPORT ) { 182 return(ENOTCONN); 183 } 184 } 185 186 s = splnet(); 187 error = ddp_output( m, so ); 188 if ( addr ) { 189 at_pcbdisconnect( ddp ); 190 } 191 splx(s); 192 return(error); 193} 194 195static int 196ddp_abort(struct socket *so) 197{ 198 struct ddpcb *ddp; 199 int s; 200 201 ddp = sotoddpcb( so ); 202 if ( ddp == NULL ) { 203 return(EINVAL); 204 } 205 soisdisconnected( so ); 206 s = splnet(); 207 at_pcbdetach( so, ddp ); 208 splx(s); 209 return(0); 210} 211 212 213static void 214at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr) 215{ 216 *addr = dup_sockaddr((struct sockaddr *)&ddp->ddp_lsat, 0); 217} 218 219static int 220at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr, struct proc *p) 221{ 222 struct sockaddr_at lsat, *sat; 223 struct at_ifaddr *aa; 224 struct ddpcb *ddpp; 225 226 if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT ) { /* shouldn't be bound */ 227 return( EINVAL ); 228 } 229 230 if (addr != 0) { /* validate passed address */ 231 sat = (struct sockaddr_at *)addr; 232 if (sat->sat_family != AF_APPLETALK) { 233 return(EAFNOSUPPORT); 234 } 235 236 if ( sat->sat_addr.s_node != ATADDR_ANYNODE || 237 sat->sat_addr.s_net != ATADDR_ANYNET ) { 238 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 239 if (( sat->sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) && 240 ( sat->sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node )) { 241 break; 242 } 243 } 244 if ( !aa ) { 245 return( EADDRNOTAVAIL ); 246 } 247 } 248 249 if ( sat->sat_port != ATADDR_ANYPORT ) { 250 if ( sat->sat_port < ATPORT_FIRST || 251 sat->sat_port >= ATPORT_LAST ) { 252 return( EINVAL ); 253 } 254 if ( sat->sat_port < ATPORT_RESERVED && 255 suser( p->p_ucred, &p->p_acflag ) ) { 256 return( EACCES ); 257 } 258 } 259 } else { 260 bzero( (caddr_t)&lsat, sizeof( struct sockaddr_at )); 261 lsat.sat_len = sizeof(struct sockaddr_at); 262 lsat.sat_addr.s_node = ATADDR_ANYNODE; 263 lsat.sat_addr.s_net = ATADDR_ANYNET; 264 lsat.sat_family = AF_APPLETALK; 265 sat = &lsat; 266 } 267 268 if ( sat->sat_addr.s_node == ATADDR_ANYNODE && 269 sat->sat_addr.s_net == ATADDR_ANYNET ) { 270 if ( at_ifaddr == NULL ) { 271 return( EADDRNOTAVAIL ); 272 } 273 sat->sat_addr = AA_SAT( at_ifaddr )->sat_addr; 274 } 275 ddp->ddp_lsat = *sat; 276 277 /* 278 * Choose port. 279 */ 280 if ( sat->sat_port == ATADDR_ANYPORT ) { 281 for ( sat->sat_port = ATPORT_RESERVED; 282 sat->sat_port < ATPORT_LAST; sat->sat_port++ ) { 283 if ( ddp_ports[ sat->sat_port - 1 ] == 0 ) { 284 break; 285 } 286 } 287 if ( sat->sat_port == ATPORT_LAST ) { 288 return( EADDRNOTAVAIL ); 289 } 290 ddp->ddp_lsat.sat_port = sat->sat_port; 291 ddp_ports[ sat->sat_port - 1 ] = ddp; 292 } else { 293 for ( ddpp = ddp_ports[ sat->sat_port - 1 ]; ddpp; 294 ddpp = ddpp->ddp_pnext ) { 295 if ( ddpp->ddp_lsat.sat_addr.s_net == sat->sat_addr.s_net && 296 ddpp->ddp_lsat.sat_addr.s_node == sat->sat_addr.s_node ) { 297 break; 298 } 299 } 300 if ( ddpp != NULL ) { 301 return( EADDRINUSE ); 302 } 303 ddp->ddp_pnext = ddp_ports[ sat->sat_port - 1 ]; 304 ddp_ports[ sat->sat_port - 1 ] = ddp; 305 if ( ddp->ddp_pnext ) { 306 ddp->ddp_pnext->ddp_pprev = ddp; 307 } 308 } 309 310 return( 0 ); 311} 312 313static int 314at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr, struct proc *p) 315{ 316 struct sockaddr_at *sat = (struct sockaddr_at *)addr; 317 struct route *ro; 318 struct at_ifaddr *aa = 0; 319 struct ifnet *ifp; 320 u_short hintnet = 0, net; 321 322 if (sat->sat_family != AF_APPLETALK) { 323 return(EAFNOSUPPORT); 324 } 325 326 /* 327 * Under phase 2, network 0 means "the network". We take "the 328 * network" to mean the network the control block is bound to. 329 * If the control block is not bound, there is an error. 330 */ 331 if ( sat->sat_addr.s_net == ATADDR_ANYNET 332 && sat->sat_addr.s_node != ATADDR_ANYNODE ) { 333 if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) { 334 return( EADDRNOTAVAIL ); 335 } 336 hintnet = ddp->ddp_lsat.sat_addr.s_net; 337 } 338 339 ro = &ddp->ddp_route; 340 /* 341 * If we've got an old route for this pcb, check that it is valid. 342 * If we've changed our address, we may have an old "good looking" 343 * route here. Attempt to detect it. 344 */ 345 if ( ro->ro_rt ) { 346 if ( hintnet ) { 347 net = hintnet; 348 } else { 349 net = sat->sat_addr.s_net; 350 } 351 aa = 0;
|
353 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 354 if ( aa->aa_ifp == ifp && 355 ntohs( net ) >= ntohs( aa->aa_firstnet ) && 356 ntohs( net ) <= ntohs( aa->aa_lastnet )) { 357 break; 358 } 359 } 360 } 361 if ( aa == NULL || ( satosat( &ro->ro_dst )->sat_addr.s_net != 362 ( hintnet ? hintnet : sat->sat_addr.s_net ) || 363 satosat( &ro->ro_dst )->sat_addr.s_node != 364 sat->sat_addr.s_node )) { 365 RTFREE( ro->ro_rt ); 366 ro->ro_rt = (struct rtentry *)0; 367 } 368 } 369 370 /* 371 * If we've got no route for this interface, try to find one. 372 */ 373 if ( ro->ro_rt == (struct rtentry *)0 || 374 ro->ro_rt->rt_ifp == (struct ifnet *)0 ) { 375 ro->ro_dst.sa_len = sizeof( struct sockaddr_at ); 376 ro->ro_dst.sa_family = AF_APPLETALK; 377 if ( hintnet ) { 378 satosat( &ro->ro_dst )->sat_addr.s_net = hintnet; 379 } else { 380 satosat( &ro->ro_dst )->sat_addr.s_net = sat->sat_addr.s_net; 381 } 382 satosat( &ro->ro_dst )->sat_addr.s_node = sat->sat_addr.s_node; 383 rtalloc( ro ); 384 } 385 386 /* 387 * Make sure any route that we have has a valid interface. 388 */ 389 aa = 0; 390 if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) { 391 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 392 if ( aa->aa_ifp == ifp ) { 393 break; 394 } 395 } 396 } 397 if ( aa == 0 ) { 398 return( ENETUNREACH ); 399 } 400 401 ddp->ddp_fsat = *sat; 402 if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) { 403 return(at_pcbsetaddr(ddp, (struct sockaddr *)0, p)); 404 } 405 return( 0 ); 406} 407 408static void 409at_pcbdisconnect( struct ddpcb *ddp ) 410{ 411 ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET; 412 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE; 413 ddp->ddp_fsat.sat_port = ATADDR_ANYPORT; 414} 415 416static int 417at_pcballoc( struct socket *so ) 418{ 419 struct ddpcb *ddp; 420 421 MALLOC(ddp, struct ddpcb *, sizeof *ddp, M_PCB, M_WAITOK); 422 bzero(ddp, sizeof *ddp); 423 ddp->ddp_lsat.sat_port = ATADDR_ANYPORT; 424 425 ddp->ddp_next = ddpcb; 426 ddp->ddp_prev = NULL; 427 ddp->ddp_pprev = NULL; 428 ddp->ddp_pnext = NULL; 429 if (ddpcb) { 430 ddpcb->ddp_prev = ddp; 431 } 432 ddpcb = ddp; 433 434 ddp->ddp_socket = so; 435 so->so_pcb = (caddr_t)ddp; 436 return(0); 437} 438 439static void 440at_pcbdetach( struct socket *so, struct ddpcb *ddp) 441{ 442 soisdisconnected( so ); 443 so->so_pcb = 0; 444 sofree( so ); 445 446 /* remove ddp from ddp_ports list */ 447 if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT && 448 ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] != NULL ) { 449 if ( ddp->ddp_pprev != NULL ) { 450 ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext; 451 } else { 452 ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] = ddp->ddp_pnext; 453 } 454 if ( ddp->ddp_pnext != NULL ) { 455 ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev; 456 } 457 } 458 459 if ( ddp->ddp_route.ro_rt ) { 460 rtfree( ddp->ddp_route.ro_rt ); 461 } 462 463 if ( ddp->ddp_prev ) { 464 ddp->ddp_prev->ddp_next = ddp->ddp_next; 465 } else { 466 ddpcb = ddp->ddp_next; 467 } 468 if ( ddp->ddp_next ) { 469 ddp->ddp_next->ddp_prev = ddp->ddp_prev; 470 } 471 FREE(ddp, M_PCB); 472} 473 474/* 475 * For the moment, this just find the pcb with the correct local address. 476 * In the future, this will actually do some real searching, so we can use 477 * the sender's address to do de-multiplexing on a single port to many 478 * sockets (pcbs). 479 */ 480struct ddpcb * 481ddp_search( struct sockaddr_at *from, struct sockaddr_at *to, 482 struct at_ifaddr *aa) 483{ 484 struct ddpcb *ddp; 485 486 /* 487 * Check for bad ports. 488 */ 489 if ( to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST ) { 490 return( NULL ); 491 } 492 493 /* 494 * Make sure the local address matches the sent address. What about 495 * the interface? 496 */ 497 for ( ddp = ddp_ports[ to->sat_port - 1 ]; ddp; ddp = ddp->ddp_pnext ) { 498 /* XXX should we handle 0.YY? */ 499 500 /* XXXX.YY to socket on destination interface */ 501 if ( to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net && 502 to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node ) { 503 break; 504 } 505 506 /* 0.255 to socket on receiving interface */ 507 if ( to->sat_addr.s_node == ATADDR_BCAST && ( to->sat_addr.s_net == 0 || 508 to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net ) && 509 ddp->ddp_lsat.sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) { 510 break; 511 } 512 513 /* XXXX.0 to socket on destination interface */ 514 if ( to->sat_addr.s_net == aa->aa_firstnet && 515 to->sat_addr.s_node == 0 && 516 ntohs( ddp->ddp_lsat.sat_addr.s_net ) >= 517 ntohs( aa->aa_firstnet ) && 518 ntohs( ddp->ddp_lsat.sat_addr.s_net ) <= 519 ntohs( aa->aa_lastnet )) { 520 break; 521 } 522 } 523 return( ddp ); 524} 525static int 526at_setpeeraddr(struct socket *so, struct sockaddr **nam) 527{ 528 return(EOPNOTSUPP); 529} 530 531static int 532at_setsockaddr(struct socket *so, struct sockaddr **nam) 533{ 534 struct ddpcb *ddp; 535 536 ddp = sotoddpcb( so ); 537 if ( ddp == NULL ) { 538 return( EINVAL); 539 } 540 at_sockaddr( ddp, nam ); 541 return(0); 542} 543 544 545void 546ddp_init(void ) 547{ 548 atintrq1.ifq_maxlen = IFQ_MAXLEN; 549 atintrq2.ifq_maxlen = IFQ_MAXLEN; 550} 551 552#if 0 553static void 554ddp_clean(void ) 555{ 556 struct ddpcb *ddp; 557 558 for ( ddp = ddpcb; ddp; ddp = ddp->ddp_next ) { 559 at_pcbdetach( ddp->ddp_socket, ddp ); 560 } 561} 562#endif 563 564struct pr_usrreqs ddp_usrreqs = { 565 ddp_abort, 566 pru_accept_notsupp, 567 ddp_attach, 568 ddp_bind, 569 ddp_connect, 570 pru_connect2_notsupp, 571 at_control, 572 ddp_detach, 573 ddp_disconnect, 574 pru_listen_notsupp, 575 at_setpeeraddr, 576 pru_rcvd_notsupp, 577 pru_rcvoob_notsupp, 578 ddp_send, 579 pru_sense_null, 580 ddp_shutdown, 581 at_setsockaddr, 582 sosend, 583 soreceive, 584 sopoll 585};
|