root/net/inet/ipx.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ipx_remove_socket
  2. ipx_insert_socket
  3. ipx_find_socket
  4. ipx_destroy_socket
  5. ipx_get_info
  6. ipxrtr_get_local_net
  7. ipxrtr_get_default_net
  8. ipxrtr_get_dev
  9. ipxrtr_add_localnet
  10. ipxrtr_create
  11. ipxrtr_delete_localnet
  12. ipxrtr_delete
  13. ipxrtr_ioctl
  14. ipx_rt_get_info
  15. ipx_fcntl
  16. ipx_setsockopt
  17. ipx_getsockopt
  18. ipx_listen
  19. def_callback1
  20. def_callback2
  21. ipx_create
  22. ipx_dup
  23. ipx_release
  24. first_free_socketnum
  25. ipx_bind
  26. ipx_connect
  27. ipx_socketpair
  28. ipx_accept
  29. ipx_getname
  30. ipx_rcv
  31. ipx_sendto
  32. ipx_send
  33. ipx_recvfrom
  34. ipx_write
  35. ipx_recv
  36. ipx_read
  37. ipx_shutdown
  38. ipx_select
  39. ipx_ioctl
  40. ipx_proto_init

   1 /*
   2  *      Implements an IPX socket layer (badly - but I'm working on it).
   3  *
   4  *      This code is derived from work by
   5  *              Ross Biro       :       Writing the original IP stack
   6  *              Fred Van Kempen :       Tidying up the TCP/IP
   7  *
   8  *      Many thanks go to Keith Baker, Institute For Industrial Information
   9  *      Technology Ltd, Swansea University for allowing me to work on this
  10  *      in my own time even though it was in some ways related to commercial
  11  *      work I am currently employed to do there.
  12  *
  13  *      All the material in this file is subject to the Gnu license version 2.
  14  *      Neither Alan Cox nor the Swansea University Computer Society admit liability
  15  *      nor provide warranty for any of this software. This material is provided 
  16  *      as is and at no charge.         
  17  *
  18  *      Revision 0.21:  Uses the new generic socket option code.
  19  *      Revision 0.22:  Gcc clean ups and drop out device registration. Use the
  20  *                      new multi-protocol edition of hard_header 
  21  *      Revision 0.23:  IPX /proc by Mark Evans.
  22  *                      Adding a route will overwrite any existing route to the same
  23  *                      network.
  24  *      Revision 0.24:  Supports new /proc with no 4K limit
  25  *      Revision 0.25:  Add ephemeral sockets, passive local network 
  26  *                      identification, support for local net 0 and
  27  *                      multiple datalinks
  28  *                      
  29  *
  30  */
  31  
  32 #include <linux/config.h>
  33 #include <linux/errno.h>
  34 #include <linux/types.h>
  35 #include <linux/socket.h>
  36 #include <linux/in.h>
  37 #include <linux/kernel.h>
  38 #include <linux/sched.h>
  39 #include <linux/timer.h>
  40 #include <linux/string.h>
  41 #include <linux/sockios.h>
  42 #include <linux/net.h>
  43 #include <linux/ipx.h>
  44 #include <linux/inet.h>
  45 #include <linux/netdevice.h>
  46 #include <linux/skbuff.h>
  47 #include "sock.h"
  48 #include <asm/segment.h>
  49 #include <asm/system.h>
  50 #include <linux/fcntl.h>
  51 #include <linux/mm.h>
  52 #include <linux/interrupt.h>
  53 #include "p8022.h"
  54 
  55 #ifdef CONFIG_IPX
  56 /***********************************************************************************************************************\
  57 *                                                                                                                       *
  58 *                                               Handlers for the socket list.                                           *
  59 *                                                                                                                       *
  60 \***********************************************************************************************************************/
  61 
  62 static ipx_socket *volatile ipx_socket_list=NULL;
  63 
  64 /*
  65  *      Note: Sockets may not be removed _during_ an interrupt or inet_bh
  66  *      handler using this technique. They can be added although we do not
  67  *      use this facility.
  68  */
  69  
  70 static void ipx_remove_socket(ipx_socket *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         ipx_socket *s;
  73         
  74         cli();
  75         s=ipx_socket_list;
  76         if(s==sk)
  77         {
  78                 ipx_socket_list=s->next;
  79                 sti();
  80                 return;
  81         }
  82         while(s && s->next)
  83         {
  84                 if(s->next==sk)
  85                 {
  86                         s->next=sk->next;
  87                         sti();
  88                         return;
  89                 }
  90                 s=s->next;
  91         }
  92         sti();
  93 }
  94 
  95 static void ipx_insert_socket(ipx_socket *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97         cli();
  98         sk->next=ipx_socket_list;
  99         ipx_socket_list=sk;
 100         sti();
 101 }
 102 
 103 static ipx_socket *ipx_find_socket(int port)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         ipx_socket *s;
 106         s=ipx_socket_list;
 107         while(s)
 108         {
 109                 if(s->ipx_source_addr.sock==port)
 110                 {
 111                         return(s);
 112                 }
 113                 s=s->next;
 114         }
 115         return(NULL);
 116 }
 117 
 118 /*
 119  *      This is only called from user mode. Thus it protects itself against
 120  *      interrupt users but doesn't worry about being called during work.
 121  *      Once it is removed from the queue no interrupt or bottom half will
 122  *      touch it and we are (fairly 8-) ) safe.
 123  */
 124  
 125 static void ipx_destroy_socket(ipx_socket *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127         struct sk_buff *skb;
 128         ipx_remove_socket(sk);
 129         
 130         while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
 131         {
 132                 kfree_skb(skb,FREE_READ);
 133         }
 134         
 135         kfree_s(sk,sizeof(*sk));
 136 }
 137 
 138 
 139 /* Called from proc fs */
 140 int ipx_get_info(char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 141 {
 142         ipx_socket *s;
 143         int len=0;
 144         off_t pos=0;
 145         off_t begin=0;
 146 
 147         /* Theory.. Keep printing in the same place until we pass offset */
 148         
 149         len += sprintf (buffer,"Type local_address             rem_address              tx_queue rx_queue st uid\n");
 150         for (s = ipx_socket_list; s != NULL; s = s->next)
 151         {
 152                 len += sprintf (buffer+len,"%02X   ", s->ipx_type);
 153                 len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%02X ", htonl(s->ipx_source_addr.net),
 154                         s->ipx_source_addr.node[0], s->ipx_source_addr.node[1], s->ipx_source_addr.node[2],
 155                         s->ipx_source_addr.node[3], s->ipx_source_addr.node[4], s->ipx_source_addr.node[5],
 156                         htons(s->ipx_source_addr.sock));
 157                 len += sprintf (buffer+len,"%08lX:%02X%02X%02X%02X%02X%02X:%02X ", htonl(s->ipx_dest_addr.net),
 158                         s->ipx_dest_addr.node[0], s->ipx_dest_addr.node[1], s->ipx_dest_addr.node[2],
 159                         s->ipx_dest_addr.node[3], s->ipx_dest_addr.node[4], s->ipx_dest_addr.node[5],
 160                         htons(s->ipx_dest_addr.sock));
 161                 len += sprintf (buffer+len,"%08lX:%08lX ", s->wmem_alloc, s->rmem_alloc);
 162                 len += sprintf (buffer+len,"%02X %d\n", s->state, SOCK_INODE(s->socket)->i_uid);
 163                 
 164                 /* Are we still dumping unwanted data then discard the record */
 165                 pos=begin+len;
 166                 
 167                 if(pos<offset)
 168                 {
 169                         len=0;                  /* Keep dumping into the buffer start */
 170                         begin=pos;
 171                 }
 172                 if(pos>offset+length)           /* We have dumped enough */
 173                         break;
 174         }
 175         
 176         /* The data in question runs from begin to begin+len */
 177         *start=buffer+(offset-begin);   /* Start of wanted data */
 178         len-=(offset-begin);            /* Remove unwanted header data from lenth */
 179         if(len>length)
 180                 len=length;             /* Remove unwanted tail data from length */
 181         
 182         return len;
 183 }
 184 
 185 /*******************************************************************************************************************\
 186 *                                                                                                                   *
 187 *                                       Routing tables for the IPX socket layer                                     *
 188 *                                                                                                                   *
 189 \*******************************************************************************************************************/
 190 
 191 
 192 static struct datalink_proto    *p8022_datalink = NULL;
 193 static struct datalink_proto    *pEII_datalink = NULL;
 194 static struct datalink_proto    *p8023_datalink = NULL;
 195 static struct datalink_proto    *pSNAP_datalink = NULL;
 196 
 197 static ipx_route *ipx_router_list=NULL;
 198 static ipx_route *ipx_localnet_list=NULL;
 199 
 200 static ipx_route *
 201 ipxrtr_get_local_net(struct device *dev, unsigned short datalink)
     /* [previous][next][first][last][top][bottom][index][help] */
 202 {
 203         ipx_route *r;
 204         unsigned long flags;
 205         save_flags(flags);
 206         cli();
 207         r=ipx_localnet_list;
 208         while(r!=NULL)
 209         {
 210                 if((r->dev==dev) && (r->dlink_type == datalink))
 211                 {
 212                         restore_flags(flags);
 213                         return r;
 214                 }
 215                 r=r->next;
 216         }
 217         restore_flags(flags);
 218         return NULL;
 219 }
 220         
 221 static ipx_route *
 222 ipxrtr_get_default_net(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 223 {
 224         return ipx_localnet_list;
 225 }
 226 
 227 static ipx_route *ipxrtr_get_dev(long net)
     /* [previous][next][first][last][top][bottom][index][help] */
 228 {
 229         ipx_route *r;
 230         unsigned long flags;
 231         save_flags(flags);
 232         cli();
 233         r=ipx_router_list;
 234         while(r!=NULL)
 235         {
 236                 if(r->net==net)
 237                 {
 238                         restore_flags(flags);
 239                         return r;
 240                 }
 241                 r=r->next;
 242         }
 243         restore_flags(flags);
 244         return NULL;
 245 }
 246 
 247 static void ipxrtr_add_localnet(ipx_route *newnet)
     /* [previous][next][first][last][top][bottom][index][help] */
 248 {
 249         ipx_route *r;
 250         unsigned long flags;
 251         save_flags(flags);
 252         cli();
 253 
 254         newnet->nextlocal = NULL;
 255         if (ipx_localnet_list == NULL) {
 256                 ipx_localnet_list = newnet;
 257                 restore_flags(flags);
 258                 return;
 259         }
 260 
 261         r=ipx_localnet_list;
 262         while(r->nextlocal!=NULL)
 263                 r=r->nextlocal;
 264 
 265         r->nextlocal = newnet;
 266         
 267         restore_flags(flags);
 268         return;
 269 }
 270 
 271 static int ipxrtr_create(struct ipx_route_def *r)
     /* [previous][next][first][last][top][bottom][index][help] */
 272 {
 273         ipx_route *rt=ipxrtr_get_dev(r->ipx_network);
 274         struct device *dev;
 275         unsigned short  dlink_type;
 276         struct datalink_proto *datalink = NULL;
 277 
 278         if (r->ipx_flags & IPX_RT_BLUEBOOK) {
 279                 dlink_type = htons(ETH_P_IPX);
 280                 datalink = pEII_datalink;
 281         } else if (r->ipx_flags & IPX_RT_8022) {
 282                 dlink_type = htons(ETH_P_802_2);
 283                 datalink = p8022_datalink;
 284         } else if (r->ipx_flags & IPX_RT_SNAP) {
 285                 dlink_type = htons(ETH_P_SNAP);
 286                 datalink = pSNAP_datalink;
 287         } else {
 288                 dlink_type = htons(ETH_P_802_3);
 289                 datalink = p8023_datalink;
 290         }
 291 
 292         if (datalink == NULL) {
 293                 printk("IPX: Unsupported datalink protocol.\n");
 294                 return -EPROTONOSUPPORT;
 295         }
 296 
 297         if(r->ipx_router_network!=0)
 298         {
 299                 /* Adding an indirect route */
 300                 ipx_route *rt1=ipxrtr_get_dev(r->ipx_router_network);
 301                 if(rt1==NULL)
 302                         return -ENETUNREACH;
 303                 if(rt1->flags&IPX_RT_ROUTED)
 304                         return -EMULTIHOP;
 305                 if (rt==NULL)
 306                 {
 307                         rt=(ipx_route *)kmalloc(sizeof(ipx_route),GFP_ATOMIC);  /* Because we are brave and don't lock the table! */
 308                         if(rt==NULL)
 309                                 return -EAGAIN;
 310                         rt->next=ipx_router_list;
 311                         ipx_router_list=rt;
 312                 }
 313                 rt->net=r->ipx_network;
 314                 rt->router_net=r->ipx_router_network;
 315                 memcpy(rt->router_node,r->ipx_router_node,sizeof(rt->router_node));
 316                 rt->flags=IPX_RT_ROUTED;
 317                 rt->dlink_type = dlink_type;
 318                 rt->datalink = datalink;
 319                 rt->dev=rt1->dev;
 320                 return 0;
 321         }
 322         /* Add a direct route */
 323         dev=dev_get(r->ipx_device);
 324         if(dev==NULL)
 325                 return -ENODEV;
 326         /* Check addresses are suitable */
 327         if(dev->addr_len>6)
 328                 return -EINVAL;
 329         if(dev->addr_len<2)
 330                 return -EINVAL;
 331         if (ipxrtr_get_local_net(dev, dlink_type) != NULL)
 332                 return -EEXIST;
 333         /* Ok now create */
 334         rt=(ipx_route *)kmalloc(sizeof(ipx_route),GFP_ATOMIC);  /* Because we are brave and don't lock the table! */
 335         if(rt==NULL)
 336                 return -EAGAIN;
 337         rt->next=ipx_router_list;
 338         ipx_router_list=rt;
 339         rt->router_net=0;
 340         memset(rt->router_node,0,sizeof(rt->router_node));
 341         rt->dev=dev;
 342         rt->net=r->ipx_network;
 343         rt->flags=0;
 344         rt->dlink_type = dlink_type;
 345         rt->datalink = datalink;
 346         ipxrtr_add_localnet(rt);
 347         return 0;
 348 }
 349 
 350 
 351 static int ipxrtr_delete_localnet(ipx_route *d)
     /* [previous][next][first][last][top][bottom][index][help] */
 352 {
 353         ipx_route *r=ipx_localnet_list;
 354         if(r==d)
 355         {
 356                 ipx_localnet_list=r->next;
 357                 return 0;
 358         }
 359         while(r->next!=NULL)
 360         {
 361                 if(r->nextlocal==d)
 362                 {
 363                         r->nextlocal=d->nextlocal;
 364                         return 0;
 365                 }
 366                 r=r->nextlocal;
 367         }
 368         return -ENOENT;
 369 }
 370 
 371 static int ipxrtr_delete(long net)
     /* [previous][next][first][last][top][bottom][index][help] */
 372 {
 373         ipx_route *r=ipx_router_list;
 374         if(r->net==net)
 375         {
 376                 ipx_router_list=r->next;
 377                 kfree_s(r,sizeof(ipx_route));
 378                 return 0;
 379         }
 380         while(r->next!=NULL)
 381         {
 382                 if(r->next->net==net)
 383                 {
 384                         ipx_route *d=r->next;
 385                         r->next=d->next;
 386                         if (d->router_net == 0) {
 387                                 ipxrtr_delete_localnet(d);
 388                         }
 389                         kfree_s(d,sizeof(ipx_route));
 390                         return 0;
 391                 }
 392                 r=r->next;
 393         }
 394         return -ENOENT;
 395 }
 396 
 397 static int ipxrtr_ioctl(unsigned int cmd, void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 398 {
 399         int err;
 400         switch(cmd)
 401         {
 402                 case SIOCDELRT:
 403                         err=verify_area(VERIFY_READ,arg,sizeof(long));
 404                         if(err)
 405                                 return err;
 406                         return ipxrtr_delete(get_fs_long(arg));
 407                 case SIOCADDRT:
 408                 {
 409                         struct ipx_route_def f;
 410                         err=verify_area(VERIFY_READ,arg,sizeof(f));
 411                         if(err)
 412                                 return err;
 413                         memcpy_fromfs(&f,arg,sizeof(f));
 414                         return ipxrtr_create(&f);
 415                 }
 416                 default:
 417                         return -EINVAL;
 418         }
 419 }
 420 
 421 /* Called from proc fs */
 422 int ipx_rt_get_info(char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 423 {
 424         ipx_route *rt;
 425         int len=0;
 426         off_t pos=0;
 427         off_t begin=0;
 428 
 429         len += sprintf (buffer,"Net      Router                Flags Dev\n");
 430         for (rt = ipx_router_list; rt != NULL; rt = rt->next)
 431         {
 432                 len += sprintf (buffer+len,"%08lX %08lX:%02X%02X%02X%02X%02X%02X %02X    %s\n", ntohl(rt->net),
 433                         ntohl(rt->router_net), rt->router_node[0], rt->router_node[1], rt->router_node[2],
 434                         rt->router_node[3], rt->router_node[4], rt->router_node[5], rt->flags, rt->dev->name);
 435                 pos=begin+len;
 436                 if(pos<offset)
 437                 {
 438                         len=0;
 439                         begin=pos;
 440                 }
 441                 if(pos>offset+length)
 442                         break;
 443         }
 444         *start=buffer+(offset-begin);
 445         len-=(offset-begin);
 446         if(len>length)
 447                 len=length;
 448         return len;
 449 }
 450 
 451 /*******************************************************************************************************************\
 452 *                                                                                                                   *
 453 *             Handling for system calls applied via the various interfaces to an IPX socket object                  *
 454 *                                                                                                                   *
 455 \*******************************************************************************************************************/
 456  
 457 static int ipx_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 458 {
 459         ipx_socket *sk;
 460         
 461         sk=(ipx_socket *)sock->data;
 462         
 463         if(sk==NULL)
 464         {
 465                 printk("IPX:fcntl:passed sock->data=NULL\n");
 466                 return(0);
 467         }
 468         
 469         switch(cmd)
 470         {
 471                 default:
 472                         return(-EINVAL);
 473         }
 474 }
 475 
 476 static int ipx_setsockopt(struct socket *sock, int level, int optname,
     /* [previous][next][first][last][top][bottom][index][help] */
 477         char *optval, int optlen)
 478 {
 479         ipx_socket *sk;
 480         int err,opt;
 481         
 482         sk=(ipx_socket *)sock->data;
 483         
 484         if(sk==NULL)
 485         {
 486                 printk("IPX:setsockopt:passed sock->data=NULL\n");
 487                 return 0;
 488         }
 489         
 490         if(optval==NULL)
 491                 return(-EINVAL);
 492         err=verify_area(VERIFY_READ,optval,sizeof(int));
 493         if(err)
 494                 return err;
 495         opt=get_fs_long((unsigned long *)optval);
 496         
 497         switch(level)
 498         {
 499                 case SOL_IPX:
 500                         switch(optname)
 501                         {
 502                                 case IPX_TYPE:
 503                                         if(!suser())
 504                                                 return(-EPERM);
 505                                         sk->ipx_type=opt;
 506                                         return 0;
 507                                 default:
 508                                         return -EOPNOTSUPP;
 509                         }
 510                         break;
 511                         
 512                 case SOL_SOCKET:                
 513                         return sock_setsockopt(sk,level,optname,optval,optlen);
 514 
 515                 default:
 516                         return -EOPNOTSUPP;
 517         }
 518 }
 519 
 520 static int ipx_getsockopt(struct socket *sock, int level, int optname,
     /* [previous][next][first][last][top][bottom][index][help] */
 521         char *optval, int *optlen)
 522 {
 523         ipx_socket *sk;
 524         int val=0;
 525         int err;
 526         
 527         sk=(ipx_socket *)sock->data;
 528         if(sk==NULL)
 529         {
 530                 printk("IPX:getsockopt:passed NULL sock->data.\n");
 531                 return 0;
 532         }
 533 
 534         switch(level)
 535         {
 536 
 537                 case SOL_IPX:
 538                         switch(optname)
 539                         {
 540                                 case IPX_TYPE:
 541                                         val=sk->ipx_type;
 542                                         break;
 543                                 default:
 544                                         return -ENOPROTOOPT;
 545                         }
 546                         break;
 547                         
 548                 case SOL_SOCKET:
 549                         return sock_getsockopt(sk,level,optname,optval,optlen);
 550                         
 551                 default:
 552                         return -EOPNOTSUPP;
 553         }
 554         err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
 555         if(err)
 556                 return err;
 557         put_fs_long(sizeof(int),(unsigned long *)optlen);
 558         err=verify_area(VERIFY_WRITE,optval,sizeof(int));
 559         put_fs_long(val,(unsigned long *)optval);
 560         return(0);
 561 }
 562 
 563 static int ipx_listen(struct socket *sock, int backlog)
     /* [previous][next][first][last][top][bottom][index][help] */
 564 {
 565         return -EOPNOTSUPP;
 566 }
 567 
 568 static void def_callback1(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 569 {
 570         if(!sk->dead)
 571                 wake_up_interruptible(sk->sleep);
 572 }
 573 
 574 static void def_callback2(struct sock *sk, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 575 {
 576         if(!sk->dead)
 577                 wake_up_interruptible(sk->sleep);
 578 }
 579 
 580 static int ipx_create(struct socket *sock, int protocol)
     /* [previous][next][first][last][top][bottom][index][help] */
 581 {
 582         ipx_socket *sk;
 583         sk=(ipx_socket *)kmalloc(sizeof(*sk),GFP_KERNEL);
 584         if(sk==NULL)
 585                 return(-ENOMEM);
 586         switch(sock->type)
 587         {
 588                 case SOCK_DGRAM:
 589                         break;
 590                 default:
 591                         kfree_s((void *)sk,sizeof(*sk));
 592                         return(-ESOCKTNOSUPPORT);
 593         }
 594         sk->dead=0;
 595         sk->next=NULL;
 596         sk->broadcast=0;
 597         sk->rcvbuf=SK_RMEM_MAX;
 598         sk->sndbuf=SK_WMEM_MAX;
 599         sk->wmem_alloc=0;
 600         sk->rmem_alloc=0;
 601         sk->inuse=0;
 602         sk->shutdown=0;
 603         sk->prot=NULL;  /* So we use default free mechanisms */
 604         sk->broadcast=0;
 605         sk->err=0;
 606         skb_queue_head_init(&sk->receive_queue);
 607         skb_queue_head_init(&sk->write_queue);
 608         sk->send_head=NULL;
 609         skb_queue_head_init(&sk->back_log);
 610         sk->state=TCP_CLOSE;
 611         sk->socket=sock;
 612         sk->type=sock->type;
 613         sk->ipx_type=0;         /* General user level IPX */
 614         sk->debug=0;
 615         
 616         memset(&sk->ipx_dest_addr,'\0',sizeof(sk->ipx_dest_addr));
 617         memset(&sk->ipx_source_addr,'\0',sizeof(sk->ipx_source_addr));
 618         sk->mtu=IPX_MTU;
 619         
 620         if(sock!=NULL)
 621         {
 622                 sock->data=(void *)sk;
 623                 sk->sleep=sock->wait;
 624         }
 625         
 626         sk->state_change=def_callback1;
 627         sk->data_ready=def_callback2;
 628         sk->write_space=def_callback1;
 629         sk->error_report=def_callback1;
 630 
 631         sk->zapped=1;
 632         return(0);
 633 }
 634 
 635 static int ipx_dup(struct socket *newsock,struct socket *oldsock)
     /* [previous][next][first][last][top][bottom][index][help] */
 636 {
 637         return(ipx_create(newsock,SOCK_DGRAM));
 638 }
 639 
 640 static int ipx_release(struct socket *sock, struct socket *peer)
     /* [previous][next][first][last][top][bottom][index][help] */
 641 {
 642         ipx_socket *sk=(ipx_socket *)sock->data;
 643         if(sk==NULL)
 644                 return(0);
 645         if(!sk->dead)
 646                 sk->state_change(sk);
 647         sk->dead=1;
 648         sock->data=NULL;
 649         ipx_destroy_socket(sk);
 650         return(0);
 651 }
 652                 
 653 static unsigned short first_free_socketnum(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 654 {
 655         static unsigned short   socketNum = 0x4000;
 656         unsigned short  startNum, foundNum = 0;
 657 
 658         startNum = socketNum;
 659         do {
 660                 if (ipx_find_socket(htons(socketNum)) == NULL) {
 661                         foundNum = socketNum;
 662                 }
 663                 socketNum++;
 664                 if (socketNum > 0x7ffc) socketNum = 0x4000;
 665         }       while (!foundNum && (socketNum != startNum));
 666 
 667         return  htons(foundNum);
 668 }
 669         
 670 static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 671 {
 672         ipx_socket *sk;
 673         int err;
 674         struct sockaddr_ipx addr;
 675         struct ipx_route *rt;
 676         unsigned char   *nodestart;
 677         
 678         sk=(ipx_socket *)sock->data;
 679         if(sk==NULL)
 680         {
 681                 printk("IPX:bind:sock->data=NULL\n");
 682                 return 0;
 683         }
 684         
 685         if(sk->zapped==0)
 686                 return(-EIO);
 687                 
 688         err=verify_area(VERIFY_READ,uaddr,addr_len);
 689         if(err)
 690                 return err;
 691         if(addr_len!=sizeof(addr))
 692                 return -EINVAL;
 693         memcpy_fromfs(&addr,uaddr,addr_len);
 694         
 695         if (addr.sipx_port == 0) {
 696                 addr.sipx_port = first_free_socketnum();
 697                 if (addr.sipx_port == 0) return -EINVAL;
 698         }
 699                 
 700         if(ntohs(addr.sipx_port)<0x4000 && !suser())
 701                 return(-EPERM); /* protect IPX system stuff like routing/sap */
 702         
 703         /* Source addresses are easy. It must be our network:node pair for
 704            an interface routed to IPX with the ipx routing ioctl() */
 705 
 706         if(ipx_find_socket(addr.sipx_port)!=NULL)
 707         {
 708                 if(sk->debug)
 709                         printk("IPX: bind failed because port %X in use.\n",
 710                                 (int)addr.sipx_port);
 711                 return -EADDRINUSE;        
 712         }
 713 
 714         sk->ipx_source_addr.sock=addr.sipx_port;
 715 
 716         if (addr.sipx_network == 0L) {
 717                 rt = ipxrtr_get_default_net();
 718         } else {
 719                 rt = ipxrtr_get_dev(addr.sipx_network);
 720         }
 721 
 722         if(rt == NULL)
 723         {
 724                 if(sk->debug)
 725                         printk("IPX: bind failed (no device for net %lX)\n",
 726                                 sk->ipx_source_addr.net);
 727                 return -EADDRNOTAVAIL;
 728         }
 729 
 730         sk->ipx_source_addr.net=rt->net;
 731 
 732         /* IPX addresses zero pad physical addresses less than 6 */
 733         memset(sk->ipx_source_addr.node,'\0',6);
 734         nodestart = sk->ipx_source_addr.node + (6 - rt->dev->addr_len);
 735         memcpy(nodestart,rt->dev->dev_addr,rt->dev->addr_len);
 736 
 737         ipx_insert_socket(sk);
 738         sk->zapped=0;
 739         if(sk->debug)
 740                 printk("IPX: socket is bound.\n");
 741         return(0);
 742 }
 743 
 744 static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 745         int addr_len, int flags)
 746 {
 747         ipx_socket *sk=(ipx_socket *)sock->data;
 748         struct sockaddr_ipx addr;
 749         int err;
 750         
 751         if(sk==NULL)
 752         {
 753                 printk("IPX:connect:sock->data=NULL!\n");
 754                 return 0;
 755         }
 756 
 757         sk->state = TCP_CLOSE;  
 758         sock->state = SS_UNCONNECTED;
 759         
 760         if(addr_len!=sizeof(addr))
 761                 return(-EINVAL);
 762         err=verify_area(VERIFY_READ,uaddr,addr_len);
 763         if(err)
 764                 return err;
 765         memcpy_fromfs(&addr,uaddr,sizeof(addr));
 766         
 767         if(sk->ipx_source_addr.net==0)  /* Must bind first - no autobinding in this */
 768                 return -EINVAL;
 769                 
 770         
 771         sk->ipx_dest_addr.net=addr.sipx_network;
 772         sk->ipx_dest_addr.sock=addr.sipx_port;
 773         memcpy(sk->ipx_dest_addr.node,addr.sipx_node,sizeof(sk->ipx_source_addr.node));
 774         if(ipxrtr_get_dev(sk->ipx_dest_addr.net)==NULL)
 775                 return -ENETUNREACH;
 776         sock->state = SS_CONNECTED;
 777         sk->state=TCP_ESTABLISHED;
 778         return(0);
 779 }
 780 
 781 static int ipx_socketpair(struct socket *sock1, struct socket *sock2)
     /* [previous][next][first][last][top][bottom][index][help] */
 782 {
 783         return(-EOPNOTSUPP);
 784 }
 785 
 786 static int ipx_accept(struct socket *sock, struct socket *newsock, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 787 {
 788         if(newsock->data)
 789                 kfree_s(newsock->data,sizeof(ipx_socket));
 790         return -EOPNOTSUPP;
 791 }
 792 
 793 static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 794         int *uaddr_len, int peer)
 795 {
 796         ipx_address *addr;
 797         struct sockaddr_ipx sipx;
 798         ipx_socket *sk;
 799         int len;
 800         int err;
 801         
 802         sk=(ipx_socket *)sock->data;
 803         
 804         err = verify_area(VERIFY_WRITE,uaddr_len,sizeof(long));
 805         if(err)
 806                 return err;
 807                 
 808         len = get_fs_long(uaddr_len);
 809         
 810         err = verify_area(VERIFY_WRITE, uaddr, len);
 811         if(err)
 812                 return err;
 813         
 814         if(len<sizeof(struct sockaddr_ipx))
 815                 return -EINVAL;
 816                 
 817         if(peer)
 818         {
 819                 if(sk->state!=TCP_ESTABLISHED)
 820                         return -ENOTCONN;
 821                 addr=&sk->ipx_dest_addr;
 822         }
 823         else
 824                 addr=&sk->ipx_source_addr;
 825                 
 826         sipx.sipx_family = AF_IPX;
 827         sipx.sipx_port = addr->sock;
 828         sipx.sipx_network = addr->net;
 829         memcpy(sipx.sipx_node,addr->node,sizeof(sipx.sipx_node));
 830         memcpy_tofs(uaddr,&sipx,sizeof(sipx));
 831         put_fs_long(len,uaddr_len);
 832         return(0);
 833 }
 834 
 835 int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
     /* [previous][next][first][last][top][bottom][index][help] */
 836 {
 837         /* NULL here for pt means the packet was looped back */
 838         ipx_socket *sock;
 839         ipx_packet *ipx;
 840         ipx_route *rt;
 841         ipx_route *ln;
 842         unsigned char IPXaddr[6];
 843         
 844         ipx=(ipx_packet *)skb->h.raw;
 845         
 846         if(ipx->ipx_checksum!=IPX_NO_CHECKSUM)
 847         {
 848                 /* We don't do checksum options. We can't really. Novell don't seem to have documented them.
 849                    If you need them try the XNS checksum since IPX is basically XNS in disguise. It might be
 850                    the same... */
 851                 kfree_skb(skb,FREE_READ);
 852                 return(0);
 853         }
 854         
 855         /* Too small */
 856         if(htons(ipx->ipx_pktsize)<sizeof(ipx_packet))
 857         {
 858                 kfree_skb(skb,FREE_READ);
 859                 return(0);
 860         }
 861         
 862         /* Too many hops */
 863         if(ipx->ipx_tctrl>16)
 864         {
 865                 kfree_skb(skb,FREE_READ);
 866                 return(0);
 867         }
 868         
 869         /* Determine what local ipx endpoint this is */
 870         ln = ipxrtr_get_local_net(dev, pt->type);
 871         if (ln == NULL) 
 872         {
 873                 kfree_skb(skb,FREE_READ);
 874                 return(0);
 875         }
 876 
 877         memset(IPXaddr, '\0', 6);
 878         memcpy(IPXaddr+(6 - dev->addr_len), dev->dev_addr, dev->addr_len);
 879 
 880         /* Not us/broadcast */
 881         if(memcmp(IPXaddr,ipx->ipx_dest.node,6)!=0
 882              && memcmp(ipx_broadcast_node,ipx->ipx_dest.node,6)!=0)
 883         {
 884                 /**********************************************************************************************
 885                 
 886                         IPX router. Roughly as per the Novell spec. This doesn't handle netbios flood fill
 887                         broadcast frames. See the Novell IPX router specification for more details
 888                         (for ftp from ftp.novell.com)
 889                         
 890                 ***********************************************************************************************/
 891                 
 892                 int incoming_size;
 893                 int outgoing_size;
 894                 struct sk_buff *skb2;
 895                 int free_it=0;
 896                 
 897                 /* Rule: Don't forward packets that have exceeded the hop limit. This is fixed at 16 in IPX */
 898                 if(ipx->ipx_tctrl==16)
 899                 {
 900                         kfree_skb(skb,FREE_READ);
 901                         return(0);
 902                 }
 903 
 904                 ipx->ipx_tctrl++;
 905                 /* Don't forward if we don't have a route. We ought to go off and start hunting out routes but
 906                    if someone needs this _THEY_ can add it */           
 907                 rt=ipxrtr_get_dev(ipx->ipx_dest.net);
 908                 if(rt==NULL)   /* Unlike IP we can send on the interface we received. Eg doing DIX/802.3 conversion */
 909                 {
 910                         kfree_skb(skb,FREE_READ);
 911                         return(0);
 912                 }
 913 
 914                 /* Check for differences in outgoing and incoming packet size */
 915                 incoming_size = skb->len - ntohs(ipx->ipx_pktsize);
 916                 outgoing_size = rt->datalink->header_length + rt->dev->hard_header_len;
 917                 if(incoming_size != outgoing_size)
 918                 {
 919                         /* A different header length causes a copy. Awkward to avoid with the current
 920                            sk_buff stuff. */
 921                         skb2=alloc_skb(ntohs(ipx->ipx_pktsize) + outgoing_size,
 922                                         GFP_ATOMIC);
 923                         if(skb2==NULL)
 924                         {
 925                                 kfree_skb(skb,FREE_READ);
 926                                 return 0;
 927                         }
 928                         free_it=1;
 929                         skb2->free=1;
 930                         skb2->len=ntohs(ipx->ipx_pktsize) + outgoing_size;
 931                         skb2->mem_addr = skb2;
 932                         skb2->arp = 1;
 933                         skb2->sk = NULL;
 934 
 935                         /* Need to copy with appropriate offsets */
 936                         memcpy((char *)(skb2+1)+outgoing_size,
 937                                 (char *)(skb+1)+incoming_size,
 938                                 ntohs(ipx->ipx_pktsize));
 939                 }
 940                 else
 941                 {
 942                         skb2=skb;
 943                 }
 944 
 945                 /* Now operate on the buffer */
 946                 /* Increase hop count */
 947                 
 948                 skb2->dev = rt->dev;
 949                 rt->datalink->datalink_header(rt->datalink, skb2, 
 950                         (rt->flags&IPX_RT_ROUTED)?rt->router_node
 951                                                 :ipx->ipx_dest.node);
 952 
 953                 dev_queue_xmit(skb2,rt->dev,SOPRI_NORMAL);
 954 
 955                 if(free_it)
 956                         kfree_skb(skb,FREE_READ);
 957                 return(0);
 958         }
 959         /************ End of router: Now sanity check stuff for us ***************/
 960         
 961         /* Ok its for us ! */
 962         if (ln->net == 0L) {
 963                 printk("IPX: Registering local net %lx\n", ipx->ipx_dest.net);
 964                 ln->net = ipx->ipx_dest.net;
 965         }
 966 
 967         sock=ipx_find_socket(ipx->ipx_dest.sock);
 968         if(sock==NULL)  /* But not one of our sockets */
 969         {
 970                 kfree_skb(skb,FREE_READ);
 971                 return(0);
 972         }
 973 
 974         /* Check to see if this socket needs its network number */
 975         ln = ipxrtr_get_default_net();
 976         if (sock->ipx_source_addr.net == 0L)
 977                 sock->ipx_source_addr.net = ln->net;
 978         
 979         if(sock->rmem_alloc>=sock->rcvbuf)
 980         {
 981                 kfree_skb(skb,FREE_READ);       /* Socket is full */
 982                 return(0);
 983         }
 984         
 985         sock->rmem_alloc+=skb->mem_len;
 986         skb->sk = sock;
 987 
 988         skb_queue_tail(&sock->receive_queue,skb);
 989         if(!sock->dead)
 990                 sock->data_ready(sock,skb->len);
 991         return(0);
 992 }
 993 
 994 static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 995         unsigned flags, struct sockaddr *usip, int addr_len)
 996 {
 997         ipx_socket *sk=(ipx_socket *)sock->data;
 998         struct sockaddr_ipx *usipx=(struct sockaddr_ipx *)usip;
 999         int err;
1000         struct sockaddr_ipx sipx;
1001         struct sk_buff *skb;
1002         struct device *dev;
1003         struct ipx_packet *ipx;
1004         int size;
1005         ipx_route *rt;
1006         struct datalink_proto *dl = NULL;
1007         unsigned char IPXaddr[6];
1008         int self_addressing = 0;
1009         int broadcast = 0;
1010 
1011         if(flags)
1012                 return -EINVAL;
1013         if(len<0)
1014                 return -EINVAL;
1015         if(len == 0)
1016                 return 0;
1017                 
1018         if(usipx)
1019         {
1020                 if(addr_len <sizeof(sipx))
1021                         return(-EINVAL);
1022                 err=verify_area(VERIFY_READ,usipx,sizeof(sipx));
1023                 if(err)
1024                         return(err);
1025                 memcpy_fromfs(&sipx,usipx,sizeof(sipx));
1026                 if(sipx.sipx_family != AF_IPX)
1027                         return -EINVAL;
1028                 if(htons(sipx.sipx_port)<0x4000 && !suser())
1029                         return -EPERM;
1030         }
1031         else
1032         {
1033                 if(sk->state!=TCP_ESTABLISHED)
1034                         return -ENOTCONN;
1035                 sipx.sipx_family=AF_IPX;
1036                 sipx.sipx_port=sk->ipx_dest_addr.sock;
1037                 sipx.sipx_network=sk->ipx_dest_addr.net;
1038                 memcpy(sipx.sipx_node,sk->ipx_dest_addr.node,sizeof(sipx.sipx_node));
1039         }
1040         
1041         if(sk->debug)
1042                 printk("IPX: sendto: Addresses built.\n");
1043 
1044         if(memcmp(&sipx.sipx_node,&ipx_broadcast_node,6)==0) {
1045                 if (!sk->broadcast)
1046                         return -ENETUNREACH;
1047                 broadcast = 1;
1048         }
1049 
1050         /* Build a packet */
1051         
1052         if(sk->debug)
1053                 printk("IPX: sendto: building packet.\n");
1054         err=verify_area(VERIFY_READ,ubuf,len);
1055         if(err)
1056                 return err;
1057                 
1058         size=sizeof(ipx_packet)+len;    /* For mac headers */
1059 
1060         /* Find out where this has to go */
1061         if (sipx.sipx_network == 0L) {
1062                 rt = ipxrtr_get_default_net();
1063                 if (rt != NULL)
1064                         sipx.sipx_network = rt->net;
1065         } else
1066                 rt=ipxrtr_get_dev(sipx.sipx_network);
1067 
1068         if(rt==NULL)
1069         {
1070                 return -ENETUNREACH;
1071         }
1072         
1073         dev=rt->dev;
1074         dl = rt->datalink;
1075         
1076         size += dev->hard_header_len;
1077         size += dl->header_length;
1078 
1079         if(sk->debug)
1080                 printk("IPX: sendto: allocating buffer (%d)\n",size);
1081         
1082         if(size+sk->wmem_alloc>sk->sndbuf) {
1083                 return -EAGAIN;
1084         }
1085                 
1086         skb=alloc_skb(size,GFP_KERNEL);
1087         if(skb==NULL)
1088                 return -ENOMEM;
1089                 
1090         skb->mem_addr=skb;
1091         skb->sk=sk;
1092         skb->free=1;
1093         skb->arp=1;
1094         skb->len=size;
1095 
1096         sk->wmem_alloc+=skb->mem_len;
1097 
1098         if(sk->debug)
1099                 printk("Building MAC header.\n");               
1100         skb->dev=rt->dev;
1101         
1102         /* Build Data Link header */
1103         dl->datalink_header(dl, skb, 
1104                 (rt->flags&IPX_RT_ROUTED)?rt->router_node:sipx.sipx_node);
1105 
1106         /* See if we are sending to ourself */
1107         memset(IPXaddr, '\0', 6);
1108         memcpy(IPXaddr+(6 - skb->dev->addr_len), skb->dev->dev_addr, 
1109                         skb->dev->addr_len);
1110 
1111         self_addressing = !memcmp(IPXaddr, 
1112                                 (rt->flags&IPX_RT_ROUTED)?rt->router_node
1113                                 :sipx.sipx_node,
1114                                 6);
1115 
1116         /* Now the IPX */
1117         if(sk->debug)
1118                 printk("Building IPX Header.\n");
1119         ipx=(ipx_packet *)skb->h.raw;
1120         ipx->ipx_checksum=0xFFFF;
1121         ipx->ipx_pktsize=htons(len+sizeof(ipx_packet));
1122         ipx->ipx_tctrl=0;
1123         ipx->ipx_type=sipx.sipx_type;
1124 
1125         memcpy(&ipx->ipx_source,&sk->ipx_source_addr,sizeof(ipx->ipx_source));
1126         ipx->ipx_dest.net=sipx.sipx_network;
1127         memcpy(ipx->ipx_dest.node,sipx.sipx_node,sizeof(ipx->ipx_dest.node));
1128         ipx->ipx_dest.sock=sipx.sipx_port;
1129         if(sk->debug)
1130                 printk("IPX: Appending user data.\n");
1131         /* User data follows immediately after the IPX data */
1132         memcpy_fromfs((char *)(ipx+1),ubuf,len);
1133         if(sk->debug)
1134                 printk("IPX: Transmitting buffer\n");
1135         if((dev->flags&IFF_LOOPBACK) || self_addressing) {
1136                 struct packet_type      pt;
1137 
1138                 /* loop back */
1139                 pt.type = rt->dlink_type;
1140                 sk->wmem_alloc-=skb->mem_len;
1141                 skb->sk = NULL;
1142                 ipx_rcv(skb,dev,&pt);
1143         } else {
1144                 if (broadcast) {
1145                         struct packet_type      pt;
1146                         struct sk_buff          *skb2;
1147 
1148                         /* loop back */
1149                         pt.type = rt->dlink_type;
1150                         
1151                         skb2=alloc_skb(skb->len, GFP_ATOMIC);
1152                         skb2->mem_addr=skb2;
1153                         skb2->free=1;
1154                         skb2->arp=1;
1155                         skb2->len=skb->len;
1156                         skb2->sk = NULL;
1157                         skb2->h.raw = skb2->data + rt->datalink->header_length
1158                                 + dev->hard_header_len;
1159                         memcpy(skb2->data, skb->data, skb->len);
1160                         ipx_rcv(skb2,dev,&pt);
1161                 }
1162                 dev_queue_xmit(skb,dev,SOPRI_NORMAL);
1163         }
1164         return len;
1165 }
1166 
1167 static int ipx_send(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags)
     /* [previous][next][first][last][top][bottom][index][help] */
1168 {
1169         return ipx_sendto(sock,ubuf,size,noblock,flags,NULL,0);
1170 }
1171 
1172 static int ipx_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
1173                    unsigned flags, struct sockaddr *sip, int *addr_len)
1174 {
1175         ipx_socket *sk=(ipx_socket *)sock->data;
1176         struct sockaddr_ipx *sipx=(struct sockaddr_ipx *)sip;
1177         struct ipx_packet       *ipx = NULL;
1178         /* FILL ME IN */
1179         int copied = 0;
1180         struct sk_buff *skb;
1181         int er;
1182         
1183         if(sk->err)
1184         {
1185                 er= -sk->err;
1186                 sk->err=0;
1187                 return er;
1188         }
1189         
1190         if(size==0)
1191                 return 0;
1192         if(size<0)
1193                 return -EINVAL;
1194         if(addr_len)
1195         {
1196                 er=verify_area(VERIFY_WRITE,addr_len,sizeof(*addr_len));
1197                 if(er)
1198                         return er;
1199                 put_fs_long(sizeof(*sipx),addr_len);
1200         }
1201         if(sipx)
1202         {
1203                 er=verify_area(VERIFY_WRITE,sipx,sizeof(*sipx));
1204                 if(er)
1205                         return er;
1206         }
1207         er=verify_area(VERIFY_WRITE,ubuf,size);
1208         if(er)
1209                 return er;
1210         skb=skb_recv_datagram(sk,flags,noblock,&er);
1211         if(skb==NULL)
1212                 return er;
1213 
1214         ipx = (ipx_packet *)(skb->h.raw);
1215         copied=ntohs(ipx->ipx_pktsize) - sizeof(ipx_packet);
1216         skb_copy_datagram(skb,sizeof(struct ipx_packet),ubuf,copied);
1217         
1218         if(sipx)
1219         {
1220                 struct sockaddr_ipx addr;
1221                 
1222                 addr.sipx_family=AF_IPX;
1223                 addr.sipx_port=ipx->ipx_source.sock;
1224                 memcpy(addr.sipx_node,ipx->ipx_source.node,sizeof(addr.sipx_node));
1225                 addr.sipx_network=ipx->ipx_source.net;
1226                 addr.sipx_type = ipx->ipx_type;
1227                 memcpy_tofs(sipx,&addr,sizeof(*sipx));
1228         }
1229         skb_free_datagram(skb);
1230         return(copied);
1231 }               
1232 
1233 
1234 static int ipx_write(struct socket *sock, char *ubuf, int size, int noblock)
     /* [previous][next][first][last][top][bottom][index][help] */
1235 {
1236         return ipx_send(sock,ubuf,size,noblock,0);
1237 }
1238 
1239 
1240 static int ipx_recv(struct socket *sock, void *ubuf, int size , int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
1241         unsigned flags)
1242 {
1243         ipx_socket *sk=(ipx_socket *)sock->data;
1244         if(sk->zapped)
1245                 return -ENOTCONN;
1246         return ipx_recvfrom(sock,ubuf,size,noblock,flags,NULL, NULL);
1247 }
1248 
1249 static int ipx_read(struct socket *sock, char *ubuf, int size, int noblock)
     /* [previous][next][first][last][top][bottom][index][help] */
1250 {
1251         return ipx_recv(sock,ubuf,size,noblock,0);
1252 }
1253 
1254 
1255 static int ipx_shutdown(struct socket *sk,int how)
     /* [previous][next][first][last][top][bottom][index][help] */
1256 {
1257         return -EOPNOTSUPP;
1258 }
1259 
1260 static int ipx_select(struct socket *sock , int sel_type, select_table *wait)
     /* [previous][next][first][last][top][bottom][index][help] */
1261 {
1262         ipx_socket *sk=(ipx_socket *)sock->data;
1263         
1264         return datagram_select(sk,sel_type,wait);
1265 }
1266 
1267 static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1268 {
1269         
1270         switch(cmd)
1271         {
1272                 case SIOCADDRT:
1273                 case SIOCDELRT:
1274                         if(!suser())
1275                                 return -EPERM;
1276                         return(ipxrtr_ioctl(cmd,(void *)arg));
1277                 default:
1278                         return -EINVAL;
1279         }
1280         /*NOTREACHED*/
1281         return(0);
1282 }
1283 
1284 static struct proto_ops ipx_proto_ops = {
1285         AF_IPX,
1286         
1287         ipx_create,
1288         ipx_dup,
1289         ipx_release,
1290         ipx_bind,
1291         ipx_connect,
1292         ipx_socketpair,
1293         ipx_accept,
1294         ipx_getname,
1295         ipx_read,
1296         ipx_write,
1297         ipx_select,
1298         ipx_ioctl,
1299         ipx_listen,
1300         ipx_send,
1301         ipx_recv,
1302         ipx_sendto,
1303         ipx_recvfrom,
1304         ipx_shutdown,
1305         ipx_setsockopt,
1306         ipx_getsockopt,
1307         ipx_fcntl,
1308 };
1309 
1310 /* Called by ddi.c on kernel start up */
1311 
1312 static struct packet_type ipx_8023_packet_type = 
1313 {
1314         0,      /* MUTTER ntohs(ETH_P_8023),*/
1315         0,              /* copy */
1316         ipx_rcv,
1317         NULL,
1318         NULL,
1319 };
1320  
1321 static struct packet_type ipx_dix_packet_type = 
1322 {
1323         0,      /* MUTTER ntohs(ETH_P_IPX),*/
1324         0,              /* copy */
1325         ipx_rcv,
1326         NULL,
1327         NULL,
1328 };
1329  
1330 
1331 extern struct datalink_proto    *make_EII_client(void);
1332 extern struct datalink_proto    *make_8023_client(void);
1333 
1334 void ipx_proto_init(struct net_proto *pro)
     /* [previous][next][first][last][top][bottom][index][help] */
1335 {
1336         unsigned char   val = 0xE0;
1337         (void) sock_register(ipx_proto_ops.family, &ipx_proto_ops);
1338 
1339         pEII_datalink = make_EII_client();
1340         ipx_dix_packet_type.type=htons(ETH_P_IPX);
1341         dev_add_pack(&ipx_dix_packet_type);
1342 
1343         p8023_datalink = make_8023_client();
1344         ipx_8023_packet_type.type=htons(ETH_P_802_3);
1345         dev_add_pack(&ipx_8023_packet_type);
1346         
1347         if ((p8022_datalink = register_8022_client(val, ipx_rcv)) == NULL)
1348                 printk("IPX: Unable to register with 802.2\n");
1349         
1350         printk("Swansea University Computer Society IPX 0.25 BETA for NET3 014\n");
1351         
1352 }
1353 #endif

/* [previous][next][first][last][top][bottom][index][help] */