Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.4.1 /net/decnet/af_decnet.c

Filename:/net/decnet/af_decnet.c
Lines Added:322
Lines Deleted:245
Also changed in: (Previous) 2.4.1-pre12  2.4.1-pre11  2.4.1-pre10  2.4.0-ac12  2.4.0-ac11  2.4.0-ac10 
(Following) 2.4.1-ac9  2.4.1-ac10  2.4.1-ac11  2.4.1-ac12  2.4.1-ac13  2.4.1-ac14 

Location
[  2.4.1
  [  net
    [  decnet
       o  af_decnet.c

Patch

diff -u --recursive --new-file v2.4.0/linux/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- v2.4.0/linux/net/decnet/af_decnet.c   Mon Jan  1 09:54:07 2001
+++ linux/net/decnet/af_decnet.c   Mon Jan 29 08:07:30 2001
@@ -35,6 +35,7 @@
  *         Arnaldo C. Melo: use capable, not suser
  *        Steve Whitehouse: Removed unused code. Fix to use sk->allocation
  *                          when required.
+ *       Patrick Caulfield: /proc/net/decnet now has object name/number
  */
 
 
@@ -128,8 +129,6 @@
 #include <net/dn_fib.h>
 #include <net/dn_neigh.h>
 
-#define MAX(a,b) ((a)>(b)?(a):(b))
-
 static void dn_keepalive(struct sock *sk);
 
 /*
@@ -141,15 +140,15 @@
 
 static struct proto_ops dn_proto_ops;
 rwlock_t dn_hash_lock = RW_LOCK_UNLOCKED;
-static struct sock *dn_sklist = NULL;
-static struct sock *dn_wild_sk = NULL;
+static struct sock *dn_sklist;
+static struct sock *dn_wild_sk;
 
 static int __dn_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen, int flags);
 static int __dn_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen, int flags);
 
 static struct sock **dn_find_list(struct sock *sk)
 {
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
 
    if (scp->addr.sdn_flags & SDF_WILD)
       return dn_wild_sk ? NULL : &dn_wild_sk;
@@ -159,7 +158,7 @@
 
 static unsigned short port_alloc(struct sock *sk)
 {
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
 static unsigned short port = 0x2000;
 
    if (port == 0)
@@ -177,12 +176,17 @@
  */
 static int dn_hash_sock(struct sock *sk)
 {
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
    struct sock **skp;
    int rv = -EUSERS;
 
-   write_lock_bh(&dn_hash_lock);
+   if (sk->next)
+      BUG();
+   if (sk->pprev)
+      BUG();
 
+   write_lock_bh(&dn_hash_lock);
+   
    if (!scp->addrloc && !port_alloc(sk))
       goto out;
 
@@ -327,7 +331,7 @@
 
    read_lock(&dn_hash_lock);
    for(sk = dn_sklist; sk != NULL; sk = sk->next) {
-      struct dn_scp *scp = &sk->protinfo.dn;
+      struct dn_scp *scp = DN_SK(sk);
       if (sk->state != TCP_LISTEN)
          continue;
       if (scp->addr.sdn_objnum) {
@@ -355,13 +359,13 @@
 
 struct sock *dn_find_by_skb(struct sk_buff *skb)
 {
-   struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+   struct dn_skb_cb *cb = DN_SKB_CB(skb);
    struct sock *sk;
    struct dn_scp *scp;
 
    read_lock(&dn_hash_lock);
    for(sk = dn_sklist; sk != NULL; sk = sk->next) {
-      scp = &sk->protinfo.dn;
+      scp = DN_SK(sk);
       if (cb->src != dn_saddr2dn(&scp->peer))
          continue;
       if (cb->dst_port != scp->addrloc)
@@ -383,7 +387,7 @@
 
 static void dn_destruct(struct sock *sk)
 {
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
 
    skb_queue_purge(&scp->data_xmit_queue);
    skb_queue_purge(&scp->other_xmit_queue);
@@ -394,25 +398,26 @@
    MOD_DEC_USE_COUNT;
 }
 
-struct sock *dn_alloc_sock(struct socket *sock, int flags)
+struct sock *dn_alloc_sock(struct socket *sock, int gfp)
 {
    struct sock *sk;
    struct dn_scp *scp;
 
-   if  ((sk = sk_alloc(PF_DECnet, flags, 1)) == NULL) 
+   if  ((sk = sk_alloc(PF_DECnet, gfp, 1)) == NULL) 
       goto no_sock;
 
    if (sock) {
          sock->ops = &dn_proto_ops;
    }
    sock_init_data(sock,sk);
-   scp = &sk->protinfo.dn;
+   scp = DN_SK(sk);
 
    sk->backlog_rcv = dn_nsp_backlog_rcv;
    sk->destruct    = dn_destruct;
    sk->no_check    = 1;
    sk->family      = PF_DECnet;
    sk->protocol    = 0;
+   sk->allocation  = gfp;
 
    /* Initialization of DECnet Session Control Port      */
    scp->state   = DN_O;      /* Open         */
@@ -424,13 +429,25 @@
    scp->ackrcv_oth = 0;      /* Last oth data ack rec*/
         scp->flowrem_sw = DN_SEND;
    scp->flowloc_sw = DN_SEND;
+   scp->flowrem_dat = 0;
+   scp->flowrem_oth = 1;
+   scp->flowloc_dat = 0;
+   scp->flowloc_oth = 1;
+   scp->services_rem = 0;
+   scp->services_loc = 1 | NSP_FC_NONE;
+   scp->info_rem = 0;
+   scp->info_loc = 0x03; /* NSP version 4.1 */
+   scp->segsize_rem = 230; /* Default: Updated by remote segsize */
+   scp->segsize_loc = 1450; /* Best guess for ethernet */
+   scp->nonagle = 0;
+   scp->multi_ireq = 1;
    scp->accept_mode = ACC_IMMED;
    scp->addr.sdn_family    = AF_DECnet;
    scp->peer.sdn_family    = AF_DECnet;
    scp->accessdata.acc_accl = 5;
    memcpy(scp->accessdata.acc_acc, "LINUX", 5);
-   scp->mss = 1460;
 
+   scp->max_window   = NSP_MAX_WINDOW;
    scp->snd_window   = NSP_MIN_WINDOW;
    scp->nsp_srtt     = NSP_INITIAL_SRTT;
    scp->nsp_rttvar   = NSP_INITIAL_RTTVAR;
@@ -464,7 +481,7 @@
  */
 static void dn_keepalive(struct sock *sk)
 {
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
 
    /*
     * By checking the other_data transmit queue is empty
@@ -472,7 +489,7 @@
     * many of these keepalive frames.
     */
    if (skb_queue_len(&scp->other_xmit_queue) == 0)
-      dn_nsp_send_lnk(sk, DN_NOCHANGE);
+      dn_nsp_send_link(sk, DN_NOCHANGE, 0);
 }
 
 
@@ -485,7 +502,7 @@
  */
 int dn_destroy_timer(struct sock *sk)
 {
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
 
    scp->persist = dn_nsp_persist(sk);
 
@@ -527,7 +544,7 @@
 
 static void dn_destroy_sock(struct sock *sk)
 {
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
 
    scp->nsp_rxtshift = 0; /* reset back off */
 
@@ -674,7 +691,7 @@
 static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
    struct sock *sk = sock->sk;
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
    struct sockaddr_dn *saddr = (struct sockaddr_dn *)uaddr;
    struct net_device *dev;
    int rv;
@@ -722,11 +739,8 @@
    memcpy(&scp->addr, saddr, addr_len);
    sk->zapped = 0;
 
-   if ((rv = dn_hash_sock(sk)) == 0)
-      goto out;
-
-   sk->zapped = 1;
-out:
+   if ((rv = dn_hash_sock(sk)) != 0)
+      sk->zapped = 1;
 
         return rv;
 }
@@ -735,7 +749,7 @@
 static int dn_auto_bind(struct socket *sock)
 {
    struct sock *sk = sock->sk;
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
 
    sk->zapped = 0;
 
@@ -769,7 +783,7 @@
 {
    struct sockaddr_dn *addr = (struct sockaddr_dn *)uaddr;
    struct sock *sk = sock->sk;
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
    int err = -EISCONN;
 
    lock_sock(sk);
@@ -788,7 +802,7 @@
    }
 
    err = -EINVAL;
-   if (sk->protinfo.dn.state != DN_O)
+   if (DN_SK(sk)->state != DN_O)
       goto out;
 
    if (addr_len != sizeof(struct sockaddr_dn))
@@ -812,7 +826,7 @@
 
    sk->state   = TCP_SYN_SENT;
    sock->state = SS_CONNECTING;
-   sk->protinfo.dn.state = DN_CI;
+   DN_SK(sk)->state = DN_CI;
 
    dn_nsp_send_conninit(sk, NSP_CI);
 
@@ -853,7 +867,7 @@
         return err;
 }
 
-static int dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc)
+static void dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc)
 {
         unsigned char *ptr = skb->data;
 
@@ -870,10 +884,9 @@
 
         skb_pull(skb, acc->acc_accl + acc->acc_passl + acc->acc_userl + 3);
 
-   return 0;
 }
 
-static int dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt)
+static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt)
 {
         unsigned char *ptr = skb->data;
         
@@ -882,7 +895,6 @@
         memcpy(opt->opt_data, ptr, opt->opt_optl);
         skb_pull(skb, opt->opt_optl + 1);
 
-   return 0;
 }
 
 
@@ -910,7 +922,7 @@
                         return -ERESTARTSYS; /* But of course you don't! */
         }
 
-        if ((sk->protinfo.dn.state != DN_RUN) && (sk->protinfo.dn.state != DN_DRC)) {
+        if ((DN_SK(sk)->state != DN_RUN) && (DN_SK(sk)->state != DN_DRC)) {
                 sock->state = SS_UNCONNECTED;
                 return sock_error(sk);
         }
@@ -937,7 +949,7 @@
       return -EINVAL;
    }
 
-   if (sk->protinfo.dn.state != DN_O) {
+   if (DN_SK(sk)->state != DN_O) {
       release_sock(sk);
       return -EINVAL;
    }
@@ -967,7 +979,7 @@
                 }
         } while (skb == NULL);
 
-   cb = (struct dn_skb_cb *)skb->cb;
+   cb = DN_SKB_CB(skb);
 
    if ((newsk = dn_alloc_sock(newsock, sk->allocation)) == NULL) {
       release_sock(sk);
@@ -980,50 +992,52 @@
    dst_release(xchg(&newsk->dst_cache, skb->dst));
    skb->dst = NULL;
 
-        newsk->protinfo.dn.state      = DN_CR;
-   newsk->protinfo.dn.addrrem    = cb->src_port;
-   newsk->protinfo.dn.mss        = cb->segsize;
-   newsk->protinfo.dn.accept_mode = sk->protinfo.dn.accept_mode;
+        DN_SK(newsk)->state        = DN_CR;
+   DN_SK(newsk)->addrrem      = cb->src_port;
+   DN_SK(newsk)->services_rem = cb->services;
+   DN_SK(newsk)->info_rem     = cb->info;
+   DN_SK(newsk)->segsize_rem  = cb->segsize;
+   DN_SK(newsk)->accept_mode  = DN_SK(sk)->accept_mode;
    
-   if (newsk->protinfo.dn.mss < 230)
-      newsk->protinfo.dn.mss = 230;
+   if (DN_SK(newsk)->segsize_rem < 230)
+      DN_SK(newsk)->segsize_rem = 230;
 
    newsk->state  = TCP_LISTEN;
    newsk->zapped = 0;
 
-   memcpy(&newsk->protinfo.dn.addr, &sk->protinfo.dn.addr, sizeof(struct sockaddr_dn));
+   memcpy(&(DN_SK(newsk)->addr), &(DN_SK(sk)->addr), sizeof(struct sockaddr_dn));
 
    /*
     * If we are listening on a wild socket, we don't want
     * the newly created socket on the wrong hash queue.
     */
-   newsk->protinfo.dn.addr.sdn_flags &= ~SDF_WILD;
+   DN_SK(newsk)->addr.sdn_flags &= ~SDF_WILD;
 
-   skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &newsk->protinfo.dn.addr, &type));
-   skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &newsk->protinfo.dn.peer, &type));
-   *(dn_address *)newsk->protinfo.dn.peer.sdn_add.a_addr = cb->src;
-   *(dn_address *)newsk->protinfo.dn.addr.sdn_add.a_addr = cb->dst;
+   skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->addr), &type));
+   skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->peer), &type));
+   *(dn_address *)(DN_SK(newsk)->peer.sdn_add.a_addr) = cb->src;
+   *(dn_address *)(DN_SK(newsk)->addr.sdn_add.a_addr) = cb->dst;
 
    menuver = *skb->data;
    skb_pull(skb, 1);
 
    if (menuver & DN_MENUVER_ACC)
-      dn_access_copy(skb, &newsk->protinfo.dn.accessdata);
+      dn_access_copy(skb, &(DN_SK(newsk)->accessdata));
 
    if (menuver & DN_MENUVER_USR)
-      dn_user_copy(skb, &newsk->protinfo.dn.conndata_in);
+      dn_user_copy(skb, &(DN_SK(newsk)->conndata_in));
 
    if (menuver & DN_MENUVER_PRX)
-      newsk->protinfo.dn.peer.sdn_flags |= SDF_PROXY;
+      DN_SK(newsk)->peer.sdn_flags |= SDF_PROXY;
 
    if (menuver & DN_MENUVER_UIC)
-      newsk->protinfo.dn.peer.sdn_flags |= SDF_UICPROXY;
+      DN_SK(newsk)->peer.sdn_flags |= SDF_UICPROXY;
 
    kfree_skb(skb);
 
-   memcpy(&newsk->protinfo.dn.conndata_out, &sk->protinfo.dn.conndata_out,
+   memcpy(&(DN_SK(newsk)->conndata_out), &(DN_SK(sk)->conndata_out),
       sizeof(struct optdata_dn));
-   memcpy(&newsk->protinfo.dn.discdata_out, &sk->protinfo.dn.discdata_out,
+   memcpy(&(DN_SK(newsk)->discdata_out), &(DN_SK(sk)->discdata_out),
       sizeof(struct optdata_dn));
 
    lock_sock(newsk);
@@ -1031,9 +1045,13 @@
 
    dn_send_conn_ack(newsk);
 
-   if (newsk->protinfo.dn.accept_mode == ACC_IMMED) {
-      newsk->protinfo.dn.state = DN_CC;
-           dn_send_conn_conf(newsk, newsk->allocation);
+   /*
+    * Here we use sk->allocation since although the conn conf is
+    * for the newsk, the context is the old socket.
+    */
+   if (DN_SK(newsk)->accept_mode == ACC_IMMED) {
+      DN_SK(newsk)->state = DN_CC;
+           dn_send_conn_conf(newsk, sk->allocation);
       err = dn_wait_accept(newsock, flags);
    }
 
@@ -1046,7 +1064,7 @@
 {
    struct sockaddr_dn *sa = (struct sockaddr_dn *)uaddr;
    struct sock *sk = sock->sk;
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
 
    *uaddr_len = sizeof(struct sockaddr_dn);
 
@@ -1070,7 +1088,7 @@
 static unsigned int dn_poll(struct file *file, struct socket *sock, poll_table  *wait)
 {
    struct sock *sk = sock->sk;
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
    int mask = datagram_poll(file, sock, wait);
 
    if (skb_queue_len(&scp->other_receive_queue))
@@ -1082,100 +1100,32 @@
 static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
    struct sock *sk = sock->sk;
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
    int err = -EOPNOTSUPP;
    unsigned long amount = 0;
    struct sk_buff *skb;
+   int val;
 
-#if 0
-   struct dn_naddr dnaddr;
-#endif
    switch(cmd)
    {
    case SIOCGIFADDR:
    case SIOCSIFADDR:
       return dn_dev_ioctl(cmd, (void *)arg);
 
+   case SIOCATMARK:
+      lock_sock(sk);
+      val = (skb_queue_len(&scp->other_receive_queue) != 0);
+      if (scp->state != DN_RUN)
+         val = -ENOTCONN;
+      release_sock(sk);
+      return val;
+
 #ifdef CONFIG_DECNET_ROUTER
    case SIOCADDRT:
    case SIOCDELRT:
       return dn_fib_ioctl(sock, cmd, arg);
 #endif /* CONFIG_DECNET_ROUTER */
 
-#if 0
-   case SIOCSIFADDR:
-      if (!capable(CAP_NET_ADMIN))    return -EPERM;
-
-      if ((err = copy_from_user(devname, ioarg->devname, 5)) != 0)
-         break;
-      if ((err = copy_from_user(addr, ioarg->exec_addr, 6)) != 0)
-         break;
-      if ((dev = dev_get(devname)) == NULL) {
-         err = -ENODEV;
-         break;
-      }
-      if (dev->dn_ptr == NULL) {
-         err = -ENODEV;
-         break;
-      }
-
-      dn_dev_devices_off();
-
-      decnet_default_device = dev;
-      memcpy(decnet_ether_address, addr, ETH_ALEN);
-      decnet_address = dn_htons(dn_eth2dn(decnet_ether_address));
-
-      dn_dev_devices_on();
-
-      break;
-
-   case SIOCGIFADDR:
-      if (decnet_default_device)
-         strcpy(devname, decnet_default_device->name);
-      else
-         memset(devname, 0, 6);
-
-      if ((err = copy_to_user(ioarg->devname, devname, 5)) != 0)
-         break;
-
-      if ((err = copy_to_user(ioarg->exec_addr, decnet_ether_address, 6)) != 0)
-         break;
-
-      break;
-#endif
-
-#if 0
-   case SIOCSNETADDR:
-      if (!capable(CAP_NET_ADMIN)) {
-         err = -EPERM;
-         break;
-      }
-
-      if ((err = copy_from_user(&dnaddr, (void *)arg, sizeof(struct dn_naddr))) != 0)
-         break;
-
-      if (dnaddr.a_len != ETH_ALEN) {
-         err = -EINVAL;
-         break;
-      }
-
-      dn_dev_devices_off();
-
-      memcpy(decnet_ether_address, dnaddr.a_addr, ETH_ALEN);
-      decnet_address = dn_htons(dn_eth2dn(decnet_ether_address));
-
-      dn_dev_devices_on();
-      break;
-
-   case SIOCGNETADDR:
-      dnaddr.a_len = ETH_ALEN;
-      memcpy(dnaddr.a_addr, decnet_ether_address, ETH_ALEN);
-
-      if ((err = copy_to_user((void *)arg, &dnaddr, sizeof(struct dn_naddr))) != 0)
-         break;
-
-      break;
-#endif
    case OSIOCSNETADDR:
       if (!capable(CAP_NET_ADMIN)) {
          err = -EPERM;
@@ -1237,7 +1187,7 @@
    if (sk->zapped)
       goto out;
 
-   if ((sk->protinfo.dn.state != DN_O) || (sk->state == TCP_LISTEN))
+   if ((DN_SK(sk)->state != DN_O) || (sk->state == TCP_LISTEN))
       goto out;
 
    sk->max_ack_backlog = backlog;
@@ -1255,7 +1205,7 @@
 static int dn_shutdown(struct socket *sock, int how)
 {
    struct sock *sk = sock->sk;
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
    int err = -ENOTCONN;
 
    lock_sock(sk);
@@ -1300,14 +1250,27 @@
 static int __dn_setsockopt(struct socket *sock, int level,int optname, char *optval, int optlen, int flags) 
 {
    struct   sock *sk = sock->sk;
-   struct dn_scp *scp = &sk->protinfo.dn;
-   struct optdata_dn opt;
-   struct accessdata_dn acc;
+   struct dn_scp *scp = DN_SK(sk);
+   union {
+      struct optdata_dn opt;
+      struct accessdata_dn acc;
+      int mode;
+      unsigned long win;
+      int val;
+      unsigned char services;
+      unsigned char info;
+   } u;
    int err;
 
    if (optlen && !optval)
       return -EINVAL;
 
+   if (optlen > sizeof(u))
+      return -EINVAL;
+
+   if (copy_from_user(&u, optval, optlen))
+      return -EFAULT;
+
    switch(optname) {
       case DSO_CONDATA:
          if (sock->state == SS_CONNECTED) 
@@ -1318,29 +1281,23 @@
          if (optlen != sizeof(struct optdata_dn))
             return -EINVAL;
 
-         if (copy_from_user(&opt, optval, optlen))
-            return -EFAULT;
-
-         if (opt.opt_optl > 16)
+         if (u.opt.opt_optl > 16)
             return -EINVAL;
 
-         memcpy(&scp->conndata_out, &opt, sizeof(struct optdata_dn));
+         memcpy(&scp->conndata_out, &u.opt, optlen);
          break;
 
       case DSO_DISDATA:
-                 if (sock->state != SS_CONNECTED && sk->protinfo.dn.accept_mode == ACC_IMMED)
+                 if (sock->state != SS_CONNECTED && scp->accept_mode == ACC_IMMED)
             return -ENOTCONN;
 
          if (optlen != sizeof(struct optdata_dn))
             return -EINVAL;
 
-         if (copy_from_user(&opt, optval, sizeof(struct optdata_dn)))
-            return -EFAULT;
-
-         if (opt.opt_optl > 16)
+         if (u.opt.opt_optl > 16)
             return -EINVAL;
 
-         memcpy(&scp->discdata_out, &opt, sizeof(struct optdata_dn));
+         memcpy(&scp->discdata_out, &u.opt, optlen);
          break;
 
       case DSO_CONACCESS:
@@ -1352,15 +1309,12 @@
          if (optlen != sizeof(struct accessdata_dn))
             return -EINVAL;
 
-         if (copy_from_user(&acc, optval, sizeof(struct accessdata_dn)))
-            return -EFAULT;
-
-         if ((acc.acc_accl > DN_MAXACCL) ||
-               (acc.acc_passl > DN_MAXACCL) ||
-               (acc.acc_userl > DN_MAXACCL))
+         if ((u.acc.acc_accl > DN_MAXACCL) ||
+               (u.acc.acc_passl > DN_MAXACCL) ||
+               (u.acc.acc_userl > DN_MAXACCL))
             return -EINVAL;
 
-         memcpy(&scp->accessdata, &acc, sizeof(struct accessdata_dn));
+         memcpy(&scp->accessdata, &u.acc, optlen);
          break;
 
       case DSO_ACCEPTMODE:
@@ -1372,16 +1326,10 @@
          if (optlen != sizeof(int))
             return -EINVAL;
 
-         {
-            int mode;
-
-            if (get_user(mode, optval))
-               return -EFAULT;
-            if ((mode != ACC_IMMED) && (mode != ACC_DEFER))
-               return -EINVAL;
+         if ((u.mode != ACC_IMMED) && (u.mode != ACC_DEFER))
+            return -EINVAL;
 
-            scp->accept_mode = (unsigned char)mode;
-         }
+         scp->accept_mode = (unsigned char)u.mode;
          break;
 
       case DSO_CONACCEPT:
@@ -1411,8 +1359,55 @@
       case DSO_LINKINFO:
       case DSO_STREAM:
       case DSO_SEQPACKET:
-
          return -ENOPROTOOPT;
+
+      case DSO_MAXWINDOW:
+         if (optlen != sizeof(unsigned long))
+            return -EINVAL;
+         if (u.win > NSP_MAX_WINDOW)
+            u.win = NSP_MAX_WINDOW;
+         if (u.win == 0)
+            return -EINVAL;
+         scp->max_window = u.win;
+         if (scp->snd_window > u.win)
+            scp->snd_window = u.win;
+         break;
+
+      case DSO_NODELAY:
+         if (optlen != sizeof(int))
+            return -EINVAL;
+         if (scp->nonagle == 2)
+            return -EINVAL;
+         scp->nonagle = (u.val == 0) ? 0 : 1;
+         /* if (scp->nonagle == 1) { Push pending frames } */
+         break;
+
+      case DSO_CORK:
+         if (optlen != sizeof(int))
+            return -EINVAL;
+         if (scp->nonagle == 1)
+            return -EINVAL;
+         scp->nonagle = (u.val == 0) ? 0 : 2;
+         /* if (scp->nonagle == 0) { Push pending frames } */
+         break;
+
+      case DSO_SERVICES:
+         if (optlen != sizeof(unsigned char))
+            return -EINVAL;
+         if ((u.services & ~NSP_FC_MASK) != 0x01)
+            return -EINVAL;
+         if ((u.services & NSP_FC_MASK) == NSP_FC_MASK)
+            return -EINVAL;
+         scp->services_loc = u.services;
+         break;
+
+      case DSO_INFO:
+         if (optlen != sizeof(unsigned char))
+            return -EINVAL;
+         if (u.info & 0xfc)
+            return -EINVAL;
+         scp->info_loc = u.info;
+         break;
    }
 
    return 0;
@@ -1433,44 +1428,40 @@
 static int __dn_getsockopt(struct socket *sock, int level,int optname, char *optval,int *optlen, int flags)
 {
    struct   sock *sk = sock->sk;
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
    struct linkinfo_dn link;
-   int mode = scp->accept_mode;
+   int r_len = *optlen;
+   void *r_data = NULL;
+   int val;
 
    switch(optname) {
       case DSO_CONDATA:
-         if (*optlen != sizeof(struct optdata_dn))
-            return -EINVAL;
-
-         if (copy_to_user(optval, &scp->conndata_in, sizeof(struct optdata_dn)))
-            return -EFAULT;
+         if (r_len > sizeof(struct optdata_dn))
+            r_len = sizeof(struct optdata_dn);
+         r_data = &scp->conndata_in;
          break;
 
       case DSO_DISDATA:
-         if (*optlen != sizeof(struct optdata_dn))
-            return -EINVAL;
-
-         if (copy_to_user(optval, &scp->discdata_in, sizeof(struct optdata_dn)))
-            return -EFAULT;
-
+         if (r_len > sizeof(struct optdata_dn))
+            r_len = sizeof(struct optdata_dn);
+         r_data = &scp->discdata_in;
          break;
 
       case DSO_CONACCESS:
-         if (*optlen != sizeof(struct accessdata_dn))
-            return -EINVAL;
-
-         if (copy_to_user(optval, &scp->accessdata, sizeof(struct accessdata_dn)))
-            return -EFAULT;
+         if (r_len > sizeof(struct accessdata_dn))
+            r_len = sizeof(struct accessdata_dn);
+         r_data = &scp->accessdata;
          break;
 
       case DSO_ACCEPTMODE:
-         if (put_user(mode, optval))
-            return -EFAULT;
+         if (r_len > sizeof(unsigned char))
+            r_len = sizeof(unsigned char);
+         r_data = &scp->accept_mode;
          break;
 
       case DSO_LINKINFO:
-         if (*optlen != sizeof(struct linkinfo_dn))
-            return -EINVAL;
+         if (r_len > sizeof(struct linkinfo_dn))
+            r_len = sizeof(struct linkinfo_dn);
 
          switch(sock->state) {
             case SS_CONNECTING:
@@ -1486,10 +1477,8 @@
                link.idn_linkstate = LL_INACTIVE;
          }
 
-         link.idn_segsize = scp->mss;
-
-         if (copy_to_user(optval, &link, sizeof(struct linkinfo_dn)))
-            return -EFAULT;
+         link.idn_segsize = scp->segsize_rem;
+         r_data = &link;
          break;
 
       default:
@@ -1508,6 +1497,45 @@
       case DSO_CONACCEPT:
       case DSO_CONREJECT:
               return -ENOPROTOOPT;
+
+      case DSO_MAXWINDOW:
+         if (r_len > sizeof(unsigned long))
+            r_len = sizeof(unsigned long);
+         r_data = &scp->max_window;
+         break;
+
+      case DSO_NODELAY:
+         if (r_len > sizeof(int))
+            r_len = sizeof(int);
+         val = (scp->nonagle == 1);
+         r_data = &val;
+         break;
+
+      case DSO_CORK:
+         if (r_len > sizeof(int))
+            r_len = sizeof(int);
+         val = (scp->nonagle == 2);
+         r_data = &val;
+         break;
+
+      case DSO_SERVICES:
+         if (r_len > sizeof(unsigned char))
+            r_len = sizeof(unsigned char);
+         r_data = &scp->services_rem;
+         break;
+
+      case DSO_INFO:
+         if (r_len > sizeof(unsigned char))
+            r_len = sizeof(unsigned char);
+         r_data = &scp->info_rem;
+         break;
+   }
+
+   if (r_data) {
+      if (copy_to_user(optval, r_data, r_len))
+         return -EFAULT;
+      if (put_user(r_len, optlen))
+         return -EFAULT;
    }
 
    return 0;
@@ -1520,7 +1548,7 @@
  */
 static int dn_wait_run(struct sock *sk, int flags)
 {
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
    int err = 0;
 
    switch(scp->state) {
@@ -1572,7 +1600,7 @@
       return skb_queue_len(q) ? 1 : 0;
 
    while(skb != (struct sk_buff *)q) {
-      struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+      struct dn_skb_cb *cb = DN_SKB_CB(skb);
       len += skb->len;
 
       if (cb->nsp_flags & 0x40) {
@@ -1599,7 +1627,7 @@
    int flags, struct scm_cookie *scm)
 {
    struct sock *sk = sock->sk;
-   struct dn_scp *scp = &sk->protinfo.dn;
+   struct dn_scp *scp = DN_SK(sk);
    struct sk_buff_head *queue = &sk->receive_queue;
    int target = size > 1 ? 1 : 0;
    int copied = 0;
@@ -1681,7 +1709,7 @@
 
    for(skb = queue->next; skb != (struct sk_buff *)queue; skb = nskb) {
       int chunk = skb->len;
-      cb = (struct dn_skb_cb *)skb->cb;
+      cb = DN_SKB_CB(skb);
 
       if ((chunk + copied) > size)
          chunk = size - copied;
@@ -1693,7 +1721,7 @@
       copied += chunk;
 
       if (!(flags & MSG_PEEK))
-         skb->len -= chunk;
+         skb_pull(skb, chunk);
 
       eor = cb->nsp_flags & 0x40;
       nskb = skb->next;
@@ -1707,7 +1735,7 @@
           */
          if ((scp->flowloc_sw == DN_DONTSEND) && !dn_congested(sk)) {
             scp->flowloc_sw = DN_SEND;
-            dn_nsp_send_lnk(sk, DN_SEND);
+            dn_nsp_send_link(sk, DN_SEND, 0);
          }
       }
 
@@ -1727,6 +1755,7 @@
 
    rv = copied;
 
+
    if (eor && (sk->type == SOCK_SEQPACKET))
       msg->msg_flags |= MSG_EOR;
 
@@ -1745,16 +1774,31 @@
 }
 
 
+static inline int dn_queue_too_long(struct dn_scp *scp, struct sk_buff_head *queue, int flags)
+{
+   unsigned char fctype = scp->services_rem & NSP_FC_MASK;
+   if (skb_queue_len(queue) >= scp->snd_window)
+      return 1;
+   if (fctype != NSP_FC_NONE) {
+      if (flags & MSG_OOB) {
+         if (scp->flowrem_oth == 0)
+            return 1;
+      } else {
+         if (scp->flowrem_dat == 0)
+            return 1;
+      }
+   }
+   return 0;
+}
+
 static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size, 
       struct scm_cookie *scm)
 {
    struct sock *sk = sock->sk;
-   struct dn_scp *scp = &sk->protinfo.dn;
-   int mss = scp->mss;
-   int mtu = 230 - 11; /* maximum value thats always safe */
+   struct dn_scp *scp = DN_SK(sk);
+   int mss;
    struct sk_buff_head *queue = &scp->data_xmit_queue;
    int flags = msg->msg_flags;
-   unsigned short numseg = 0;
    int err = 0;
    int sent = 0;
    int addr_len = msg->msg_namelen;
@@ -1765,6 +1809,7 @@
    unsigned char *ptr;
    unsigned short ack;
    int len;
+   unsigned char fctype;
 
    if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR))
       return -EOPNOTSUPP;
@@ -1801,16 +1846,19 @@
    if ((flags & MSG_TRYHARD) && sk->dst_cache)
       dst_negative_advice(&sk->dst_cache);
 
+   mss = scp->segsize_rem;
+   fctype = scp->services_rem & NSP_FC_MASK;
+
    if (sk->dst_cache && sk->dst_cache->neighbour) {
       struct dn_neigh *dn = (struct dn_neigh *)sk->dst_cache->neighbour;
-      if (dn->blksize > 230)
-         mtu = dn->blksize - 11;
+      if (dn->blksize < (mss + 11))
+         mss = dn->blksize - 11;
    }
 
    /*
     * The only difference between SEQPACKET & STREAM sockets under DECnet
-    * AFAIK is that SEQPACKET sockets set the MSG_EOR flag for the last
-    * session control message segment.
+    * is that SEQPACKET sockets set the MSG_EOR flag for the last
+    * session control message segment. 
     */
 
    if (flags & MSG_OOB) {
@@ -1822,9 +1870,6 @@
       }
    }
 
-   if (mss < mtu)
-      mtu = mss;
-
    scp->persist_fxn = dn_nsp_xmit_timeout;
 
    while(sent < size) {
@@ -1842,14 +1887,14 @@
        */
       len = size - sent;
 
-      if (len > mtu)
-         len = mtu;
+      if (len > mss)
+         len = mss;
 
       /*
        * Wait for queue size to go down below the window
        * size.
        */
-      if (skb_queue_len(queue) >= scp->snd_window) {
+      if (dn_queue_too_long(scp, queue, flags)) {
          if (flags & MSG_DONTWAIT) {
             err = -EWOULDBLOCK;
             goto out;
@@ -1857,7 +1902,7 @@
 
          SOCK_SLEEP_PRE(sk)
 
-         if (skb_queue_len(queue) >= scp->snd_window)
+         if (dn_queue_too_long(scp, queue, flags))
             schedule();
 
          SOCK_SLEEP_POST(sk)
@@ -1876,7 +1921,7 @@
       if (!skb)
          continue;
 
-      cb = (struct dn_skb_cb *)skb->cb;
+      cb = DN_SKB_CB(skb);
 
       ptr = skb_put(skb, 9);
 
@@ -1886,26 +1931,34 @@
       }
 
       if (flags & MSG_OOB) {
-         cb->segnum = scp->numoth++;
-         scp->numoth &= 0x0fff;
+         cb->segnum = scp->numoth;
+         seq_add(&scp->numoth, 1);
          msgflg = 0x30;
-         ack = scp->ackxmt_oth | 0x8000;
+         ack = (scp->numoth_rcv & 0x0FFF) | 0x8000;
+         scp->ackxmt_oth = scp->numoth_rcv;
+         if (fctype != NSP_FC_NONE)
+            scp->flowrem_oth--;
       } else {
-         cb->segnum = scp->numdat++;
-         scp->numdat &= 0x0fff;
+         cb->segnum = scp->numdat;
+         seq_add(&scp->numdat, 1);
          msgflg = 0x00;
          if (sock->type == SOCK_STREAM)
             msgflg = 0x60;
-         if (scp->seg_size == 0)
+         if (scp->seg_total == 0)
             msgflg |= 0x20;
 
-         scp->seg_size += len;
+         scp->seg_total += len;
       
          if (((sent + len) == size) && (flags & MSG_EOR)) {
             msgflg |= 0x40;
-            scp->seg_size = 0;
+            scp->seg_total = 0;
+            if (fctype == NSP_FC_SCMC)
+               scp->flowrem_dat--;
          }
-         ack = scp->ackxmt_dat | 0x8000;
+         ack = (scp->numdat_rcv & 0x0FFF) | 0x8000;
+         scp->ackxmt_dat = scp->numdat_rcv;
+         if (fctype == NSP_FC_SRC)
+            scp->flowrem_dat--;
       }
 
       *ptr++ = msgflg;
@@ -1918,8 +1971,7 @@
       *(__u16 *)ptr = dn_htons(cb->segnum);
 
       sent += len;
-      dn_nsp_queue_xmit(sk, skb, flags & MSG_OOB);
-      numseg++;
+      dn_nsp_queue_xmit(sk, skb, sk->allocation, flags & MSG_OOB);
       skb = NULL;
 
       scp->persist = dn_nsp_persist(sk);
@@ -1955,21 +2007,38 @@
 }
 
 static struct notifier_block dn_dev_notifier = {
-   dn_device_event,
-   0
+   notifier_call:   dn_device_event,
 };
 
 extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
 
-static struct packet_type dn_dix_packet_type = 
-{
-   __constant_htons(ETH_P_DNA_RT),
-   NULL,      /* All devices */
-   dn_route_rcv,
-   (void*)1,
-   NULL,
+static struct packet_type dn_dix_packet_type = {
+   type:      __constant_htons(ETH_P_DNA_RT),
+   dev:      NULL,      /* All devices */
+   func:      dn_route_rcv,
+   data:      (void*)1,
 };
 
+#define IS_NOT_PRINTABLE(x) ((x) < 32 || (x) > 126)
+
+static void dn_printable_object(struct sockaddr_dn *dn, unsigned char *buf)
+{
+   int i;
+    
+   switch (dn_ntohs(dn->sdn_objnamel)) {
+      case 0:
+         sprintf(buf, "%d", dn->sdn_objnum);
+         break;
+      default:
+         for (i = 0; i < dn_ntohs(dn->sdn_objnamel); i++) {
+            buf[i] = dn->sdn_objname[i];
+            if (IS_NOT_PRINTABLE(buf[i]))
+               buf[i] = '.';
+         }
+         buf[i] = 0;
+       }
+}
+
 static int dn_get_info(char *buffer, char **start, off_t offset, int length)
 {
    struct sock *sk;
@@ -1979,15 +2048,20 @@
    off_t begin = 0;
    char buf1[DN_ASCBUF_LEN];
    char buf2[DN_ASCBUF_LEN];
+   char local_object[DN_MAXOBJL+3];
+   char remote_object[DN_MAXOBJL+3];
 
-   len += sprintf(buffer + len, "Local                             Remote\n");
+   len += sprintf(buffer + len, "Local                                              Remote\n");
 
    read_lock(&dn_hash_lock);
    for(sk = dn_sklist; sk != NULL; sk = sk->next) {
-      scp = &sk->protinfo.dn;
+      scp = DN_SK(sk);
+
+      dn_printable_object(&scp->addr, local_object);
+      dn_printable_object(&scp->peer, remote_object);
 
       len += sprintf(buffer + len,
-            "%6s/%04X %04d:%04d %04d:%04d %01d %6s/%04X %04d:%04d %04d:%04d %01d %4s %s\n",
+            "%6s/%04X %04d:%04d %04d:%04d %01d %-16s %6s/%04X %04d:%04d %04d:%04d %01d %-16s %4s %s\n",
             dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->addr)), buf1),
             scp->addrloc,
             scp->numdat,
@@ -1995,6 +2069,7 @@
             scp->ackxmt_dat,
             scp->ackxmt_oth,
             scp->flowloc_sw,
+            local_object,
             dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->peer)), buf2),
             scp->addrrem,
             scp->numdat_rcv,
@@ -2002,6 +2077,7 @@
             scp->ackrcv_dat,
             scp->ackrcv_oth,
             scp->flowrem_sw,
+            remote_object,
             dn_state2asc(scp->state),
             ((scp->accept_mode == ACC_IMMED) ? "IMMED" : "DEFER"));
 
@@ -2026,8 +2102,8 @@
 
 
 static struct net_proto_family   dn_family_ops = {
-   AF_DECnet,
-   dn_create
+   family:      AF_DECnet,
+   create:      dn_create,
 };
 
 static struct proto_ops dn_proto_ops = {
@@ -2067,6 +2143,7 @@
 MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node");
 #endif
 
+static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.4.0-test12s (C) 1995-2000 Linux DECnet Project Team\n";
 
 static int __init decnet_init(void)
 {
@@ -2085,7 +2162,7 @@
    dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address));
 #endif
 
-        printk(KERN_INFO "NET4: DECnet for Linux: V.2.4.0-test10s (C) 1995-2000 Linux DECnet Project Team\n");
+        printk(banner);
 
    sock_register(&dn_family_ops);
    dev_add_pack(&dn_dix_packet_type);


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.