chiark / gitweb /
warning disable ordering
[chiark-tcl.git] / tuntap / tuntap.c
index 7a1d2682e79ccfbba9a507c327809429b80e1830..9486a9add8b871ca4665099322b4ce19c886973c 100644 (file)
  *    if script not supplied, cancel
  */
 
-#include "tables.h"
-#include "hbytes.h"
-
-#include <sys/ioctl.h>
-#include <linux/if.h>
-#include <linux/if_tun.h>
+#include "chiark_tcl_tuntap.h"
 
 typedef struct TunSocket {
   int ix, fd, script_llength;
@@ -26,9 +21,7 @@ typedef struct TunSocket {
   char *ifname;
 } TuntapSocket;
 
-IdDataTable tuntap_socks= { "tuntap" };
-
-int do_tuntap_socket_raw_create(ClientData cd, Tcl_Interp *ip,
+int cht_do_tuntapsocket_create_tun(ClientData cd, Tcl_Interp *ip,
                                const char *ifname, void **sock_r) {
   int fd, r;
   struct ifreq ifr;
@@ -39,18 +32,18 @@ int do_tuntap_socket_raw_create(ClientData cd, Tcl_Interp *ip,
   
   if (ifname) {
     if (strlen(ifname) > IFNAMSIZ-1) return
-      staticerr(ip,"tun interface name too long","TUNTAP IFNAME LENGTH");
+      cht_staticerr(ip,"tun interface name too long","TUNTAP IFNAME LENGTH");
     strcpy(ifr.ifr_name, ifname);
   }
 
   fd= open("/dev/net/tun", O_RDWR);
-  if (fd<0) return posixerr(ip,errno,"open /dev/net/tun");
+  if (fd<0) return cht_posixerr(ip,errno,"open /dev/net/tun");
 
-  r= setnonblock(fd,1);
-  if (r) return posixerr(ip,errno,"setnonblock tun");
+  r= cht_setnonblock(fd,1);
+  if (r) return cht_posixerr(ip,errno,"setnonblock tun");
   
   r= ioctl(fd, TUNSETIFF, (void*)&ifr);
-  if (r) return newfdposixerr(ip,fd,"ioctl TUNSETIFF");
+  if (r) return cht_newfdposixerr(ip,fd,"ioctl TUNSETIFF");
 
   sock= TALLOC(sizeof(TuntapSocket));
   sock->ix= -1;
@@ -59,25 +52,25 @@ int do_tuntap_socket_raw_create(ClientData cd, Tcl_Interp *ip,
   sock->msg_buf= 0;
   sock->ifname= TALLOC(strlen(ifr.ifr_name)+1);
   strcpy(sock->ifname, ifr.ifr_name);
-  scriptinv_init(&sock->script);
+  cht_scriptinv_init(&sock->script);
 
   *sock_r= sock;
   return TCL_OK;
 }
 
-int do_tuntap_socket_raw_receive(ClientData cd, Tcl_Interp *ip,
+int cht_do_tuntapsocket_receive(ClientData cd, Tcl_Interp *ip,
                                 void *sock_v, HBytes_Value data) {
   TuntapSocket *sock= sock_v;
   int l, r;
 
   r= write(sock->fd,
-          hbytes_data(&data), l=hbytes_len(&data));
-  if (r==-1) return posixerr(ip,errno,"write tuntap");
-  else if (r!=l) return staticerr(ip,"write tuntap gave wrong answer",0);
+          cht_hb_data(&data), l=cht_hb_len(&data));
+  if (r==-1) return cht_posixerr(ip,errno,"write tuntap");
+  else if (r!=l) return cht_staticerr(ip,"write tuntap gave wrong answer",0);
   return TCL_OK;
 }
 
-int do_tuntap_socket_raw_ifname(ClientData cd, Tcl_Interp *ip,
+int cht_do_tuntapsocket_ifname(ClientData cd, Tcl_Interp *ip,
                                void *sock_v, const char **result) {
   TuntapSocket *sock= sock_v;
   *result= sock->ifname;
@@ -85,8 +78,8 @@ int do_tuntap_socket_raw_ifname(ClientData cd, Tcl_Interp *ip,
 }
 
 static void cancel(TuntapSocket *sock) {
-  if (sock->script.obj) {
-    scriptinv_cancel(&sock->script);
+  if (sock->script.script) {
+    cht_scriptinv_cancel(&sock->script);
     Tcl_DeleteFileHandler(sock->fd);
     TFREE(sock->msg_buf);
     sock->msg_buf= 0;
@@ -104,35 +97,35 @@ static void read_call(ClientData sock_cd, int mask) {
     sz= read(sock->fd, sock->msg_buf, sock->mtu);
     if (sz == -1) {
       if (errno == EAGAIN || errno == EWOULDBLOCK) rc=0;
-      else rc= posixerr(ip,errno,"read tuntap");
+      else rc= cht_posixerr(ip,errno,"read tuntap");
       goto x_rc;
     }
 
     assert(sz <= sock->mtu);
 
-    hbytes_array(&message_val, sock->msg_buf, sz);
-    args[0]= ret_hb(ip, message_val);  hbytes_empty(&message_val);
-    args[1]= ret_iddata(ip, sock, &tuntap_socks);
-    scriptinv_invoke(&sock->script, 2, args);
+    cht_hb_array(&message_val, sock->msg_buf, sz);
+    args[0]= cht_ret_hb(ip, message_val);  cht_hb_empty(&message_val);
+    args[1]= cht_ret_iddata(ip, sock, &cht_tuntap_socks);
+    cht_scriptinv_invoke(&sock->script, 2, args);
   }
 
 x_rc:
   if (rc) Tcl_BackgroundError(ip);
 }
 
-int do_tuntap_socket_raw_on_transmit(ClientData cd, Tcl_Interp *ip,
+int cht_do_tuntapsocket_on_transmit(ClientData cd, Tcl_Interp *ip,
                                     void *sock_v,
                                     long mtu, Tcl_Obj *newscript) {
   TuntapSocket *sock= sock_v;
   int rc;
 
   if (mtu > 65536)
-    return staticerr(ip,"tuntap mtu >2^16","TUNTAP MTU OVERRUN");
+    return cht_staticerr(ip,"tuntap mtu >2^16","TUNTAP MTU OVERRUN");
 
   cancel(sock);
   
   if (newscript) {
-    rc= scriptinv_set(&sock->script,ip,newscript);
+    rc= cht_scriptinv_set(&sock->script,ip,newscript,0);
     if (rc) return rc;
     
     sock->mtu= mtu;
@@ -142,15 +135,26 @@ int do_tuntap_socket_raw_on_transmit(ClientData cd, Tcl_Interp *ip,
   return TCL_OK;
 }
 
-int do_tuntap_socket_raw_close(ClientData cd, Tcl_Interp *ip, void *sock_v) {
+static void destroy(void *sock_v) {
   TuntapSocket *sock= sock_v;
-  
-  int sockix;
   cancel(sock);
   close(sock->fd); /* nothing useful to be done with errors */
-  sockix= sock->ix;
   TFREE(sock->msg_buf);
   TFREE(sock);
-  tuntap_socks.a[sockix]= 0;
+}
+
+static void destroy_idtabcb(Tcl_Interp *ip, void *sock_v) {
+  destroy(sock_v);
+}
+
+int cht_do_tuntapsocket_close(ClientData cd, Tcl_Interp *ip, void *sock) {
+  cht_tabledataid_disposing(ip,sock,&cht_tuntap_socks);
+  destroy(sock);
   return TCL_OK;
 }
+
+const IdDataSpec cht_tuntap_socks= {
+  "tuntap", "tuntap-table", destroy_idtabcb
+};
+
+CHT_INIT(tuntap, { }, CHTI_COMMANDS(cht_tuntaptoplevel_entries))