From 5db6ba060d7efc86d1cc2f82563ee79dd74b912f Mon Sep 17 00:00:00 2001 From: Brett Gordon Date: Mon, 23 Jan 2017 09:32:11 -0500 Subject: [PATCH] netd: add support for raw sockets --- Applications/netd/fuzix-conf.h | 7 +- Applications/netd/netd.c | 108 ++++++++++++++++++++++++++++++- Applications/netd/uip.c | 113 +++++++++++++++++++++++++++++++-- Applications/netd/uip.h | 34 ++++++++++ 4 files changed, 256 insertions(+), 6 deletions(-) diff --git a/Applications/netd/fuzix-conf.h b/Applications/netd/fuzix-conf.h index 76f50510..319949ac 100644 --- a/Applications/netd/fuzix-conf.h +++ b/Applications/netd/fuzix-conf.h @@ -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)) diff --git a/Applications/netd/netd.c b/Applications/netd/netd.c index 22d2789e..d1db77dd 100644 --- a/Applications/netd/netd.c +++ b/Applications/netd/netd.c @@ -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(); diff --git a/Applications/netd/uip.c b/Applications/netd/uip.c index 50de8054..9fdc1cbd 100644 --- a/Applications/netd/uip.c +++ b/Applications/netd/uip.c @@ -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: diff --git a/Applications/netd/uip.h b/Applications/netd/uip.h index 79031040..f77c3d3b 100644 --- a/Applications/netd/uip.h +++ b/Applications/netd/uip.h @@ -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_ */ -- 2.34.1