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

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