Changes from Patch #1871 (more Raw IP functionality)

This commit is contained in:
kieranm 2003-09-10 17:14:27 +00:00
parent 5f6aececba
commit 1163a1c3ce
6 changed files with 229 additions and 37 deletions

View File

@ -194,7 +194,8 @@ netbuf_fromport(struct netbuf *buf)
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
struct struct
netconn *netconn_new(enum netconn_type t) netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
{ {
struct netconn *conn; struct netconn *conn;
struct api_msg *msg; struct api_msg *msg;
@ -217,7 +218,7 @@ netconn *netconn_new(enum netconn_type t)
conn->sem = SYS_SEM_NULL; conn->sem = SYS_SEM_NULL;
conn->state = NETCONN_NONE; conn->state = NETCONN_NONE;
conn->socket = 0; conn->socket = 0;
conn->callback = 0; conn->callback = callback;
conn->recv_avail = 0; conn->recv_avail = 0;
if((msg = memp_malloc(MEMP_API_MSG)) == NULL) { if((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
@ -226,6 +227,7 @@ netconn *netconn_new(enum netconn_type t)
} }
msg->type = API_MSG_NEWCONN; msg->type = API_MSG_NEWCONN;
msg->msg.msg.bc.port = proto; /* misusing the port field */
msg->msg.conn = conn; msg->msg.conn = conn;
api_msg_post(msg); api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL); sys_mbox_fetch(conn->mbox, NULL);
@ -238,18 +240,19 @@ netconn *netconn_new(enum netconn_type t)
return conn; return conn;
} }
/*-----------------------------------------------------------------------------------*/
struct
netconn *netconn_new(enum netconn_type t)
{
return netconn_new_with_proto_and_callback(t,0,NULL);
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
struct struct
netconn *netconn_new_with_callback(enum netconn_type t, netconn *netconn_new_with_callback(enum netconn_type t,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len)) void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
{ {
struct netconn *conn; return netconn_new_with_proto_and_callback(t,0,callback);
/* get a netconn and then initialize callback pointer and socket */
conn = netconn_new(t);
if (conn)
conn->callback = callback;
return conn;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -318,6 +321,9 @@ netconn_peer(struct netconn *conn, struct ip_addr *addr,
u16_t *port) u16_t *port)
{ {
switch (conn->type) { switch (conn->type) {
case NETCONN_RAW:
/* return an error as connecting is only a helper for upper layers */
return ERR_CONN;
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM: case NETCONN_UDPNOCHKSUM:
case NETCONN_UDP: case NETCONN_UDP:
@ -342,6 +348,10 @@ netconn_addr(struct netconn *conn, struct ip_addr **addr,
u16_t *port) u16_t *port)
{ {
switch (conn->type) { switch (conn->type) {
case NETCONN_RAW:
*addr = &(conn->pcb.raw->local_ip);
*port = conn->pcb.raw->protocol;
break;
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM: case NETCONN_UDPNOCHKSUM:
case NETCONN_UDP: case NETCONN_UDP:

View File

@ -37,6 +37,37 @@
#include "lwip/sys.h" #include "lwip/sys.h"
#include "lwip/tcpip.h" #include "lwip/tcpip.h"
#if LWIP_RAW
static int
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
struct ip_addr *addr)
{
struct netbuf *buf;
struct netconn *conn;
conn = arg;
if (!conn) return 0;
if (conn->recvmbox != SYS_MBOX_NULL) {
if (!(buf = memp_malloc(MEMP_NETBUF))) {
return 0;
}
pbuf_ref(p);
buf->p = p;
buf->ptr = p;
buf->fromaddr = addr;
buf->fromport = pcb->protocol;
conn->recv_avail += p->tot_len;
/* Register event with callback */
if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
sys_mbox_post(conn->recvmbox, buf);
}
return 0; /* do not eat the packet */
}
#endif
#if LWIP_UDP #if LWIP_UDP
static void static void
recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
@ -250,6 +281,12 @@ do_newconn(struct api_msg_msg *msg)
/* Allocate a PCB for this connection */ /* Allocate a PCB for this connection */
switch(msg->conn->type) { switch(msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new(); msg->conn->pcb.udp = udp_new();
@ -300,6 +337,11 @@ do_delconn(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
raw_remove(msg->conn->pcb.raw);
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -348,6 +390,12 @@ do_bind(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp == NULL) { if (msg->conn->pcb.tcp == NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new(); msg->conn->pcb.udp = udp_new();
@ -374,6 +422,11 @@ do_bind(struct api_msg_msg *msg)
} }
} }
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -420,6 +473,12 @@ do_connect(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp == NULL) { if (msg->conn->pcb.tcp == NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new(); msg->conn->pcb.udp = udp_new();
@ -465,6 +524,12 @@ do_connect(struct api_msg_msg *msg)
} }
} }
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
sys_mbox_post(msg->conn->mbox, NULL);
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -483,6 +548,7 @@ do_connect(struct api_msg_msg *msg)
do_connected); do_connected);
/*tcp_output(msg->conn->pcb.tcp);*/ /*tcp_output(msg->conn->pcb.tcp);*/
#endif #endif
default: default:
break; break;
} }
@ -493,6 +559,11 @@ do_disconnect(struct api_msg_msg *msg)
{ {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
/* Do nothing as connecting is only a helper for upper lwip layers */
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -514,6 +585,11 @@ do_listen(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -552,6 +628,11 @@ do_accept(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -572,6 +653,11 @@ do_send(struct api_msg_msg *msg)
{ {
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
raw_send(msg->conn->pcb.raw, msg->msg.p);
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -609,6 +695,11 @@ do_write(struct api_msg_msg *msg)
#endif #endif
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
msg->conn->err = ERR_VAL;
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -653,6 +744,10 @@ do_close(struct api_msg_msg *msg)
if (msg->conn->pcb.tcp != NULL) { if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
break;
#endif
#if LWIP_UDP #if LWIP_UDP
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
/* FALLTHROUGH */ /* FALLTHROUGH */

View File

@ -479,6 +479,7 @@ lwip_send(int s, void *data, int size, unsigned int flags)
} }
switch (netconn_type(sock->conn)) { switch (netconn_type(sock->conn)) {
case NETCONN_RAW:
case NETCONN_UDP: case NETCONN_UDP:
case NETCONN_UDPLITE: case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM: case NETCONN_UDPNOCHKSUM:
@ -567,6 +568,10 @@ lwip_socket(int domain, int type, int protocol)
/* create a netconn */ /* create a netconn */
switch (type) { switch (type) {
case SOCK_RAW:
conn = netconn_new_with_proto_and_callback(NETCONN_RAW, protocol, event_callback);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
break;
case SOCK_DGRAM: case SOCK_DGRAM:
conn = netconn_new_with_callback(NETCONN_UDP, event_callback); conn = netconn_new_with_callback(NETCONN_UDP, event_callback);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
@ -1095,6 +1100,9 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
case SO_TYPE: case SO_TYPE:
switch (sock->conn->type) { switch (sock->conn->type) {
case NETCONN_RAW:
*(int*)optval = SOCK_RAW;
break;
case NETCONN_TCP: case NETCONN_TCP:
*(int*)optval = SOCK_STREAM; *(int*)optval = SOCK_STREAM;
break; break;

View File

@ -72,13 +72,14 @@ raw_init(void)
* Determine if in incoming IP packet is covered by a RAW pcb and * Determine if in incoming IP packet is covered by a RAW pcb and
* and process it if possible * and process it if possible
* *
* Given an incoming UDP datagram (as a chain of pbufs) this function * Given an incoming IP datagram (as a chain of pbufs) this function
* finds a corresponding UDP PCB and * finds a corresponding RAW PCB and
* *
* @param pbuf pbuf to be demultiplexed to a UDP PCB. * @param pbuf pbuf to be demultiplexed to a RAW PCB.
* @param netif network interface on which the datagram was received. * @param netif network interface on which the datagram was received.
* @return 0 if packet cannot be handled (pbuf needs to be freed then) * @return 0 if packet is not eated (pbuf needs to be freed then)
* or 1 if the packet has been processed * or 1 if the packet has been eaten (pbuf needs not to be freed
* then)
* *
*/ */
int int
@ -95,7 +96,8 @@ raw_input(struct pbuf *p, struct netif *inp)
for(pcb = raw_pcbs; pcb != NULL; pcb = pcb->next) { for(pcb = raw_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->protocol == proto) { if (pcb->protocol == proto) {
if (pcb->recv) { if (pcb->recv) {
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)); if (!pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)))
return 0;
} }
pbuf_free(p); pbuf_free(p);
rc = 1; rc = 1;
@ -126,10 +128,36 @@ raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
return ERR_OK; return ERR_OK;
} }
/*-----------------------------------------------------------------------------------*/ /**
* Connect an RAW PCB. This function is required by upper layers
* of lwip. Using the raw api you could use raw_send_to() instead
*
* This will associate the RAW PCB with the remote address.
*
* @param pcb RAW PCB to be connected with remote address ipaddr and port.
* @param ipaddr remote IP address to connect with.
*
* @return lwIP error code
*
* @see raw_disconnect() and raw_send_to()
*/
err_t
raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
{
ip_addr_set(&pcb->remote_ip, ipaddr);
return ERR_OK;
}
/**
* Set the callback function if a RAW packet with the pcb's protocol
* is received. If the callback function returns a value unequal 0
* the raw packet is "eaten" and not forwarded to any other raw pcb
* including lwip itself
*/
void void
raw_recv(struct raw_pcb *pcb, raw_recv(struct raw_pcb *pcb,
void (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p, int (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
struct ip_addr *addr), struct ip_addr *addr),
void *recv_arg) void *recv_arg)
{ {
@ -151,19 +179,42 @@ raw_recv(struct raw_pcb *pcb,
* *
*/ */
err_t err_t
raw_send_payload(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr) raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
{ {
err_t err; err_t err;
struct netif *netif; struct netif *netif;
struct ip_addr *src_ip; struct ip_addr *src_ip;
struct pbuf *q; /* q will be sent down the stack */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("raw_send_payload\n")); LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_send_to\n"));
/* not enough space to add an IP header to first pbuf in given p chain? */
if (pbuf_header(p, IP_HLEN)) {
/* allocate header in new pbuf */
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
/* new header pbuf could not be allocated? */
if (q == NULL) {
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_send_to: could not allocate header\n"));
return ERR_MEM;
}
/* chain header q in front of given pbuf p */
pbuf_chain(q, p);
/* { first pbuf q points to header pbuf } */
LWIP_DEBUGF(RAW_DEBUG, ("raw_send_to: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
} else {
/* first pbuf q equals given pbuf */
q = p;
pbuf_header(q, -IP_HLEN);
}
if ((netif = ip_route(ipaddr)) == NULL) { if ((netif = ip_route(ipaddr)) == NULL) {
LWIP_DEBUGF(UDP_DEBUG | 1, ("raw_send_payload: No route to 0x%lx\n", ipaddr->addr)); LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_send_to: No route to 0x%lx\n", ipaddr->addr));
#ifdef RAW_STATS #ifdef RAW_STATS
/* ++lwip_stats.raw.rterr;*/ /* ++lwip_stats.raw.rterr;*/
#endif /* UDP_STATS */ #endif /* RAW_STATS */
if (q != p) {
pbuf_free(q);
}
return ERR_RTE; return ERR_RTE;
} }
@ -171,13 +222,32 @@ raw_send_payload(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
/* use outgoing network interface IP address as source address */ /* use outgoing network interface IP address as source address */
src_ip = &(netif->ip_addr); src_ip = &(netif->ip_addr);
} else { } else {
/* use UDP PCB local IP address as source address */ /* use RAW PCB local IP address as source address */
src_ip = &(pcb->local_ip); src_ip = &(pcb->local_ip);
} }
err = ip_output_if (p, src_ip, ipaddr, 64, pcb->tos, pcb->protocol, netif); err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
return ERR_OK; /* did we chain a header earlier? */
if (q != p) {
/* free the header */
pbuf_free(q);
}
return err;
}
/**
* Send the raw IP packet to the address given by raw_connect()
*
* @param pcb the raw pcb which to send
* @param p the ip payload to send
* @param ipaddr the destination address of the whole IP packet
*
*/
err_t
raw_send(struct raw_pcb *pcb, struct pbuf *p)
{
return raw_send_to(pcb,p,&pcb->remote_ip);
} }
/** /**
@ -198,7 +268,7 @@ raw_remove(struct raw_pcb *pcb)
raw_pcbs = raw_pcbs->next; raw_pcbs = raw_pcbs->next;
/* pcb not 1st in list */ /* pcb not 1st in list */
} else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { } else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
/* find pcb in udp_pcbs list */ /* find pcb in raw_pcbs list */
if (pcb2->next != NULL && pcb2->next == pcb) { if (pcb2->next != NULL && pcb2->next == pcb) {
/* remove pcb from list */ /* remove pcb from list */
pcb2->next = pcb->next; pcb2->next = pcb->next;
@ -229,6 +299,7 @@ raw_new(u16_t proto) {
/* initialize PCB to all zeroes */ /* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct raw_pcb)); memset(pcb, 0, sizeof(struct raw_pcb));
pcb->protocol = proto; pcb->protocol = proto;
pcb->ttl = RAW_TTL;
pcb->next = raw_pcbs; pcb->next = raw_pcbs;
raw_pcbs = pcb; raw_pcbs = pcb;
} }

View File

@ -38,6 +38,7 @@
#include "lwip/ip.h" #include "lwip/ip.h"
#include "lwip/raw.h"
#include "lwip/udp.h" #include "lwip/udp.h"
#include "lwip/tcp.h" #include "lwip/tcp.h"
@ -50,7 +51,8 @@ enum netconn_type {
NETCONN_TCP, NETCONN_TCP,
NETCONN_UDP, NETCONN_UDP,
NETCONN_UDPLITE, NETCONN_UDPLITE,
NETCONN_UDPNOCHKSUM NETCONN_UDPNOCHKSUM,
NETCONN_RAW
}; };
enum netconn_state { enum netconn_state {
@ -82,6 +84,7 @@ struct netconn {
union { union {
struct tcp_pcb *tcp; struct tcp_pcb *tcp;
struct udp_pcb *udp; struct udp_pcb *udp;
struct raw_pcb *raw;
} pcb; } pcb;
err_t err; err_t err;
sys_mbox_t mbox; sys_mbox_t mbox;
@ -121,6 +124,9 @@ struct netconn * netconn_new (enum netconn_type type);
struct struct
netconn *netconn_new_with_callback(enum netconn_type t, netconn *netconn_new_with_callback(enum netconn_type t,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len)); void (*callback)(struct netconn *, enum netconn_evt, u16_t len));
struct
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len));
err_t netconn_delete (struct netconn *conn); err_t netconn_delete (struct netconn *conn);
enum netconn_type netconn_type (struct netconn *conn); enum netconn_type netconn_type (struct netconn *conn);
err_t netconn_peer (struct netconn *conn, err_t netconn_peer (struct netconn *conn,

View File

@ -46,7 +46,7 @@ struct raw_pcb {
u16_t protocol; u16_t protocol;
void (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p, int (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
struct ip_addr *addr); struct ip_addr *addr);
void *recv_arg; void *recv_arg;
}; };
@ -56,13 +56,15 @@ struct raw_pcb {
struct raw_pcb * raw_new (u16_t proto); struct raw_pcb * raw_new (u16_t proto);
void raw_remove (struct raw_pcb *pcb); void raw_remove (struct raw_pcb *pcb);
err_t raw_bind (struct raw_pcb *pcb, struct ip_addr *ipaddr); err_t raw_bind (struct raw_pcb *pcb, struct ip_addr *ipaddr);
err_t raw_connect (struct raw_pcb *pcb, struct ip_addr *ipaddr);
void raw_recv (struct raw_pcb *pcb, void raw_recv (struct raw_pcb *pcb,
void (* recv)(void *arg, struct raw_pcb *pcb, int (* recv)(void *arg, struct raw_pcb *pcb,
struct pbuf *p, struct pbuf *p,
struct ip_addr *addr), struct ip_addr *addr),
void *recv_arg); void *recv_arg);
err_t raw_send_payload (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr); err_t raw_send_to (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr);
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
/* The following functions are the lower layer interface to RAW. */ /* The following functions are the lower layer interface to RAW. */
int raw_input (struct pbuf *p, struct netif *inp); int raw_input (struct pbuf *p, struct netif *inp);