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
#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))
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 )
{
}
}
+/* 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)
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 ){
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;
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();
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. */
#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
}
#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
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)
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);
}
#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
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
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:
#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
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_ */