+struct slip {
+ struct netlink nl;
+ struct buffer_if *buff; /* We unstuff received packets into here
+ and send them to the netlink code. */
+ bool_t pending_esc;
+ netlink_deliver_fn *netlink_to_tunnel;
+ uint32_t local_address;
+};
+
+/* Generic SLIP mangling code */
+
+static void slip_stuff(struct slip *st, struct buffer_if *buf, int fd)
+{
+ uint8_t txbuf[DEFAULT_BUFSIZE];
+ uint8_t *i;
+ uint32_t j=0;
+
+ BUF_ASSERT_USED(buf);
+
+ /* There's probably a much more efficient way of implementing this */
+ txbuf[j++]=SLIP_END;
+ for (i=buf->start; i<(buf->start+buf->size); i++) {
+ switch (*i) {
+ case SLIP_END:
+ txbuf[j++]=SLIP_ESC;
+ txbuf[j++]=SLIP_ESCEND;
+ break;
+ case SLIP_ESC:
+ txbuf[j++]=SLIP_ESC;
+ txbuf[j++]=SLIP_ESCESC;
+ break;
+ default:
+ txbuf[j++]=*i;
+ break;
+ }
+ if ((j+2)>DEFAULT_BUFSIZE) {
+ if (write(fd,txbuf,j)<0) {
+ fatal_perror("slip_stuff: write()");
+ }
+ j=0;
+ }
+ }
+ txbuf[j++]=SLIP_END;
+ if (write(fd,txbuf,j)<0) {
+ fatal_perror("slip_stuff: write()");
+ }
+ BUF_FREE(buf);
+}
+
+static void slip_unstuff(struct slip *st, uint8_t *buf, uint32_t l)
+{
+ uint32_t i;
+
+ BUF_ASSERT_USED(st->buff);
+ for (i=0; i<l; i++) {
+ if (st->pending_esc) {
+ st->pending_esc=False;
+ switch(buf[i]) {
+ case SLIP_ESCEND:
+ *(uint8_t *)buf_append(st->buff,1)=SLIP_END;
+ break;
+ case SLIP_ESCESC:
+ *(uint8_t *)buf_append(st->buff,1)=SLIP_ESC;
+ break;
+ default:
+ fatal("userv_afterpoll: bad SLIP escape character");
+ }
+ } else {
+ switch (buf[i]) {
+ case SLIP_END:
+ if (st->buff->size>0) {
+ st->netlink_to_tunnel(&st->nl,st->buff);
+ BUF_ALLOC(st->buff,"userv_afterpoll");
+ }
+ buffer_init(st->buff,st->nl.max_start_pad);
+ break;
+ case SLIP_ESC:
+ st->pending_esc=True;
+ break;
+ default:
+ *(uint8_t *)buf_append(st->buff,1)=buf[i];
+ break;
+ }
+ }
+ }
+}
+
+static void slip_init(struct slip *st, struct cloc loc, dict_t *dict,
+ cstring_t name, netlink_deliver_fn *to_host)
+{
+ st->netlink_to_tunnel=
+ netlink_init(&st->nl,st,loc,dict,
+ "netlink-userv-ipif",NULL,to_host);
+ st->buff=find_cl_if(dict,"buffer",CL_BUFFER,True,"name",loc);
+ st->local_address=string_item_to_ipaddr(
+ dict_find_item(dict,"local-address", True, name, loc),"netlink");
+ BUF_ALLOC(st->buff,"slip_init");
+ st->pending_esc=False;
+}
+