netd: add support for raw sockets
authorBrett Gordon <beretta42@gmail.com>
Mon, 23 Jan 2017 14:32:11 +0000 (09:32 -0500)
committerBrett Gordon <beretta42@gmail.com>
Mon, 23 Jan 2017 14:32:11 +0000 (09:32 -0500)
Applications/netd/fuzix-conf.h
Applications/netd/netd.c
Applications/netd/uip.c
Applications/netd/uip.h

index 76f5051..319949a 100644 (file)
@@ -7,10 +7,12 @@
 
 typedef uint8_t uip_tcp_appstate_t;
 typedef uint8_t uip_udp_appstate_t;
+typedef uint8_t uip_raw_appstate_t;
 typedef uint8_t uip_stats_t;
 
 #define UIP_APPCALL netd_appcall
 #define UIP_UDP_APPCALL netd_udp_appcall
+#define UIP_RAW_APPCALL netd_raw_appcall
 
 #define UIP_CONF_LLH_LEN 14
 
@@ -18,6 +20,9 @@ typedef uint8_t uip_stats_t;
 
 #define UIP_CONF_ACTIVE_OPEN 1
 
-#define UIP_CONF_RECEIVE_WINDOW 1500 
+#define UIP_CONF_RECEIVE_WINDOW 1500
+
+#define UIP_RAW 1
+#define UIP_RAW_CONNS 8
 
 #define MIN(n, m)   (((n) < (m)) ? (n) : (m))
index 22d2789..d1db77d 100644 (file)
@@ -135,6 +135,24 @@ void send_udp( struct link *s )
        ksend( NE_ROOM );
 }
 
+/* send raw data FIXME: fold together with send_udp */
+void send_raw( struct link *s )
+{
+       /* Send packet to net */
+       uint32_t base = s->socketn * RINGSIZ * 2 + RINGSIZ;
+       uint16_t len = s->tsize[s->tstart];
+       lseek( bfd, base + s->tstart * TXPKTSIZ, SEEK_SET );
+       if ( read( bfd, uip_appdata, len ) < 0 )
+               exit_err("cannot read from backing file\n");
+       uip_raw_send( len );
+       if ( ++s->tstart == NSOCKBUF )
+               s->tstart = 0;
+       /* Send Room event back to kernel */
+       ne.socket = s->socketn;
+       ne.data = s->tstart;
+       ksend( NE_ROOM );
+}
+
 /* return amout of free room for adding data in recv ring buffer */
 uint16_t room( struct link *s )
 {
@@ -375,6 +393,68 @@ void netd_udp_appcall()
        }
 }
 
+/* uIP callbck for UDP event */
+void netd_raw_appcall()
+{
+       /* debug
+          printe( "appcall udp: " );
+          if( uip_aborted() ) printe("aborted");
+          if( uip_acked() )  printe("acked");
+          if( uip_closed() ) printe("closed");
+          if( uip_newdata() ) printe("new data");
+          if( uip_poll() ) printe("polled");
+          if( uip_rexmit() ) printe("rexmit");
+          if( uip_timedout() ) printe("timed out");
+          if( uip_connected() ) printe("connected" );
+          printe("\n");
+       */
+
+       struct link *s = & map[uip_raw_conn->appstate];
+       ne.socket = s->socketn;
+
+       if ( uip_poll() ){
+               /* send data if there's data waiting on this connection */
+               /*    doing this before testing for close ??? */
+               if ( s->tend != s->tstart ){
+                       send_raw( s );
+                       return; /* short circuit LINK_CLOSED until EOD. */
+               }
+               /* if flagged close from kernel, then really close, confirm w/ kernel */
+               if ( s->flags & LINK_CLOSED ){
+                       /* send closed event back to kernel */
+                       ne.socket = sm.s.s_num;
+                       ne.data = SS_CLOSED;
+                       ksend( NE_NEWSTATE );
+                       /* release private link resource */
+                       rel_map( uip_raw_conn->appstate );
+                       uip_raw_remove( uip_raw_conn );
+                       return;
+               }
+       }
+
+       if ( uip_newdata() ){
+               /* there new data in the packet buffer */
+               uint16_t len = uip_datalen();
+               char *ptr = uip_appdata;
+               uint32_t base = ne.socket * RINGSIZ * 2;
+
+               if ( (s->rend + 1)&(NSOCKBUF-1) == s->rstart )
+                       return; /* full - drop it */
+               s->rsize[s->rend] = len;
+               memcpy( &ne.info, s->rsize, sizeof(uint16_t) * NSOCKBUF );
+               lseek( bfd, base + s->rend * RXPKTSIZ, SEEK_SET );
+               if ( write( bfd, ptr, len ) < 0 )
+                   exit_err("cannot write to backing file\n");
+               if ( ++s->rend == NSOCKBUF )
+                       s->rend = 0;
+               /* FIXME: throttle incoming data if there's no room in ring buf */
+               /* tell kernel we have data */
+               ne.data = s->rend;
+               /* ne.info = ???; for udp only? */
+               ksend( NE_DATA );
+       }
+}
+
 
 /* unused (for now) */
 void uip_log(char *m)
@@ -449,6 +529,24 @@ int dokernel( void )
                                        ksend( NE_NEWSTATE );
                                        break;
                                }
+                               else if ( sm.s.s_type == SOCKTYPE_RAW ){
+                                       struct uip_raw_conn *conptr;
+                                       uip_ipaddr_t addr;
+                                       int port = sm.s.s_addr[SADDR_DST].port;
+                                       uip_ipaddr_copy( &addr, (uip_ipaddr_t *)
+                                                        &sm.s.s_addr[SADDR_DST].addr );
+                                       /* need some HTONS'ing done here? */
+                                       conptr = uip_raw_new( &addr, port );
+                                       if ( !conptr ){
+                                               break; /* fixme: actually handler the error */
+                                       }
+                                       m->conn = ( struct uip_conn *)conptr; /* fixme: needed? */
+                                       conptr->appstate = sm.sd.lcn;
+                                       /* refactor: same as tcp action from connect event */
+                                       ne.data = SS_CONNECTED;
+                                       ksend( NE_NEWSTATE );
+                                       break;
+                               }
                                break; /* FIXME: handle unknown/unhandled sock types here */
                        case SS_CLOSED:
                                if ( sm.s.s_type == SOCKTYPE_TCP ){
@@ -469,7 +567,8 @@ int dokernel( void )
                                                m->flags += LINK_CLOSED;
                                        }
                                }
-                               else if ( sm.s.s_type == SOCKTYPE_UDP ){
+                               else if ( sm.s.s_type == SOCKTYPE_UDP ||
+                                       sm.s.s_type == SOCKTYPE_RAW ){
                                        m->flags += LINK_CLOSED;
                                }
                                break;
@@ -542,6 +641,13 @@ int douip( void )
                                device_send( uip_buf, uip_len );
                        }
                }
+               for (i = 0; i < UIP_RAW_CONNS; i++) {
+                       uip_raw_periodic(i);
+                       if (uip_len > 0) {
+                               uip_arp_out();
+                               device_send( uip_buf, uip_len );
+                       }
+               }
                if ( timer_expired(&arp_timer)){
                        timer_reset(&arp_timer);
                        uip_arp_timer();
index 50de805..9fdc1cb 100644 (file)
@@ -155,6 +155,12 @@ struct uip_udp_conn *uip_udp_conn;
 struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
 #endif /* UIP_UDP */
 
+
+#if UIP_RAW
+struct uip_raw_conn *uip_raw_conn;
+struct uip_raw_conn uip_raw_conns[UIP_RAW_CONNS];
+#endif /* UIP_RAW */
+
 static uint16_t ipid;           /* Ths ipid variable is an increasing
                                number that is used for the IP ID
                                field. */
@@ -212,7 +218,6 @@ static uint16_t tmp16;
 #define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
 #define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
 
-
 #if UIP_STATISTICS == 1
 struct uip_stats uip_stat;
 #define UIP_STAT(s) s
@@ -378,6 +383,12 @@ uip_init(void)
   }
 #endif /* UIP_UDP */
 
+#if UIP_RAW
+  for(c = 0; c < UIP_RAW_CONNS; ++c) {
+    uip_raw_conns[c].proto = 0;
+  }
+#endif /* UIP_RAW */
+
 
   /* IPv4 initialization. */
 #if UIP_FIXEDADDR == 0
@@ -502,6 +513,44 @@ uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport)
   return conn;
 }
 #endif /* UIP_UDP */
+
+
+#if UIP_RAW
+struct uip_raw_conn *
+uip_raw_new(const uip_ipaddr_t *ripaddr, uint8_t proto)
+{
+  register struct uip_raw_conn *conn;
+
+  /* disallow UDP,TCP ?
+  /* FIXME: check raw pool for anything already using this protocol */
+
+  /* find an unused RAW connection */
+  conn = 0;
+  for(c = 0; c < UIP_RAW_CONNS; ++c) {
+    if(uip_raw_conns[c].proto == 0) {
+      conn = &uip_raw_conns[c];
+      break;
+    }
+  }
+
+  if(conn == 0) {
+    return 0;
+  }
+
+  conn->proto = proto;
+  if(ripaddr == NULL) {
+    memset(&conn->ripaddr, 0, sizeof(uip_ipaddr_t));
+  } else {
+    uip_ipaddr_copy(&conn->ripaddr, ripaddr);
+  }
+  conn->ttl = UIP_TTL;
+
+  return conn;
+}
+#endif /* UIP_RAW */
+
+
+
 /*---------------------------------------------------------------------------*/
 void
 uip_unlisten(uint16_t port)
@@ -819,7 +868,22 @@ uip_process(uint8_t flag)
       goto drop;
     }
   }
-#endif
+#endif /* UIP_UDP */
+
+#if UIP_RAW
+  if(flag == UIP_RAW_TIMER) {
+    if(uip_raw_conn->proto != 0) {
+      uip_conn = NULL;
+      uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPH_LEN];
+      uip_len = uip_slen = 0;
+      uip_flags = UIP_POLL;
+      UIP_RAW_APPCALL();
+      goto raw_send;
+    } else {
+      goto drop;
+    }
+  }
+#endif /* UIP_RAW */
 
   /* This is where the input processing starts. */
   UIP_STAT(++uip_stat.ip.recv);
@@ -965,6 +1029,22 @@ uip_process(uint8_t flag)
   }
 #endif /* UIP_UDP */
 
+#if UIP_RAW
+  if (BUF->proto == UIP_PROTO_ICMP && ICMPBUF->type == ICMP_ECHO){
+      /* fix icmp handling now doesn't need to check for prot and type!!! */
+      goto icmp_input;
+  }
+  /* find raw socket that matches protocol */
+  for(uip_raw_conn = &uip_raw_conns[0];
+      uip_raw_conn < &uip_raw_conns[UIP_RAW_CONNS];
+      ++uip_raw_conn){
+      if(uip_raw_conn->proto !=0 &&
+        uip_raw_conn->proto == BUF->proto )
+         goto raw_found;
+  }
+  goto drop;
+#endif /* UIP_RAW */
+
 #if !NETSTACK_CONF_WITH_IPV6
   /* ICMPv4 processing code follows. */
   if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
@@ -975,9 +1055,7 @@ uip_process(uint8_t flag)
     goto drop;
   }
 
-#if UIP_PINGADDRCONF
  icmp_input:
-#endif /* UIP_PINGADDRCONF */
   UIP_STAT(++uip_stat.icmp.recv);
 
   /* ICMP echo (i.e., ping) processing. This is simple, we only change
@@ -1217,6 +1295,33 @@ uip_process(uint8_t flag)
   goto ip_send_nolen;
 #endif /* UIP_UDP */
 
+
+  /* RAW socket processing. */
+#if UIP_RAW
+ raw_found:
+  uip_len = uip_len - UIP_IPH_LEN;
+  uip_conn = NULL;
+  uip_flags = UIP_NEWDATA;
+  uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPH_LEN];
+  uip_slen = 0;
+  UIP_RAW_APPCALL();
+
+ raw_send:
+  if(uip_slen == 0 ) {
+      goto drop;
+  }
+  uip_len = uip_slen + UIP_IPH_LEN;
+  BUF->len[0] = (uip_len >> 8);
+  BUF->len[1] = (uip_len & 0xff);
+  BUF->ttl = uip_raw_conn->ttl;
+  BUF->proto = uip_raw_conn->proto;
+  uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr);
+  uip_ipaddr_copy(&BUF->destipaddr, &uip_raw_conn->ripaddr);
+  uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPH_LEN];
+  goto ip_send_nolen;
+#endif /* UIP_RAW */
+
+
   /* TCP input processing. */
 #if UIP_TCP
  tcp_input:
index 7903104..f77c3d3 100644 (file)
@@ -1603,6 +1603,10 @@ void uip_process(uint8_t flag);
 #define UIP_UDP_TIMER     5
 #endif /* UIP_UDP */
 
+#if UIP_RAW
+#define UIP_RAW_TIMER     6
+#endif /* UIP_RAW */
+
 /* The TCP states used in the uip_conn->tcpstateflags. */
 #define UIP_CLOSED      0
 #define UIP_SYN_RCVD    1
@@ -2231,6 +2235,36 @@ uint16_t uip_udpchksum(void);
 uint16_t uip_icmp6chksum(void);
 
 
+
+
+/*  Support for RAW sockets here
+ *  BMG
+ *
+ *  - all packets matching protocol go to socket/connection
+ *  - packets sent and received start at the protocol header (for now)
+ *  
+ */
+
+struct uip_raw_conn {
+    uip_ipaddr_t ripaddr;           /* IP address of remote peer */
+    uint8_t      proto;             /* IP protocol number */
+    uint8_t      ttl;               /* defualt time-to-live */
+    uip_raw_appstate_t appstate;    /* application's state */
+};
+
+extern struct uip_raw_conn *uip_raw_conn;
+extern struct uip_raw_conn uip_raw_conns[UIP_RAW_CONNS];
+
+struct uip_raw_conn *
+uip_raw_new(const uip_ipaddr_t *ripaddr, uint8_t proto);
+
+#define uip_raw_remove(conn) (conn)->proto = 0
+
+#define uip_raw_send(len) uip_send((char *)uip_appdata, len)
+
+#define uip_raw_periodic(conn) do { uip_raw_conn = &uip_raw_conns[conn]; \
+    uip_process(UIP_RAW_TIMER); } while(0)
+
 #endif /* UIP_H_ */