home *** CD-ROM | disk | FTP | other *** search
/ sustworks.com / 2014.06.sustworks.com.tar / sustworks.com / open_source_IPNetMonitor_TNKE.dmg / IPNetMonitor_TNKE.c < prev    next >
C/C++ Source or Header  |  2005-08-22  |  44KB  |  1,416 lines

  1. //
  2. //  IPNetMonitor_TNKE.c
  3. //  Mac OS X Interface Filter NKE
  4. //
  5. //  Created by psichel [PAS] on Wed Mar 27 2002.
  6. //  Based on SharedIP and TCPLogger provided as Open Source sample code
  7. //    from Apple Computer.
  8. //
  9. //    See IPNetMonitor_TNKE.h for high level design overview.
  10. //    You can send comments or suggestions to psichel@sustworks.com
  11. //    The companion IPNetMonitorX controller application is available from
  12. //        http://www.sustworks.com
  13. //
  14. // ---------------------------------------------------------------------------------
  15. //    Portions Copyright (c) 1999-2002 Apple Computer, Inc. All Rights Reserved.
  16. //
  17. //    This file contains Original Code and/or Modifications of Original Code as defined
  18. //    in and that are subject to the Apple Public Source License Version 1.2 (the 'License').
  19. //    You may not use this file except in compliance with the License.
  20. //    Please obtain a copy of the License at http://www.apple.com/publicsource
  21. //    and read it before using this file.
  22. //
  23. //    The Original Code and all software distributed under the License are distributed
  24. //    on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  25. //    AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION,
  26. //    ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  27. //    ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the specific
  28. //    language governing rights and limitations under the License." 
  29. // ---------------------------------------------------------------------------------
  30.  
  31. #define IPK_DEBUG 0
  32. // Tiger kpi (socket filter)
  33. #include <mach/vm_types.h>
  34. #include <mach/kmod.h>
  35. #include <sys/socket.h>
  36. #include <sys/kpi_socketfilter.h>
  37. #include <netinet/in.h>
  38.  
  39. // Tiger kpi (interface filter)
  40. #include <mach/mach_types.h>
  41. #include <sys/systm.h>
  42. #include <sys/queue.h>
  43. #include <sys/malloc.h>
  44. #include <sys/kpi_mbuf.h>
  45. #define _IP_VHL
  46. #include <netinet/in_systm.h>
  47. //#include <netinet/in.h>
  48. #include <netinet/ip.h>
  49. #include <netinet/ip6.h>
  50. #include <netinet/kpi_ipfilter.h>
  51. #include <net/kpi_interfacefilter.h>
  52. void iflt_detach(interface_filter_t filter_ref);
  53.  
  54. #include <sys/param.h>
  55. #include <sys/systm.h>
  56.  
  57. //#include <sys/socket.h>
  58. //#include <sys/protosw.h>
  59. //#include <sys/socketvar.h>
  60.  
  61. #include <sys/fcntl.h>
  62. //#include <sys/malloc.h>
  63. #include <sys/queue.h>
  64. #include <sys/domain.h>
  65. #include <sys/mbuf.h>
  66. #include <sys/kern_event.h>
  67. #include <net/route.h>
  68. #include <net/if.h>
  69. #include <net/if_types.h>
  70. #include <net/if_dl.h>
  71. #include <net/ndrv.h>
  72. #include <net/kext_net.h>
  73. #include <net/dlil.h>
  74. //#include <netinet/in.h>        // Needed for (*&^%$#@ arpcom in if_arp.h
  75. #include <net/ethernet.h>
  76. #include <net/if_arp.h>
  77. #include <machine/spl.h>
  78. #include <kern/thread.h>
  79. #include <libkern/OSAtomic.h>
  80. #include <libkern/OSTypes.h>
  81. #include <string.h>
  82.  
  83. #include "IPNetMonitor_TNKE.h"
  84. // tag packets so we can recognize re-injected ones
  85. #define MY_BUNDLE_ID "com.sustworks.kext.IPNetMonitor_TNKE"
  86. #define MY_TAG_TYPE 1
  87. // tag associated with this kext for use in marking packets that have been previously processed
  88. static mbuf_tag_id_t    gidtag;
  89.  
  90. int     memcmp(const void *, const void *, size_t);
  91.  
  92. // macro to convert kernel to external socket
  93. //#define sotoextcb(so) (struct kextcb *)(so->so_ext)
  94.  
  95. //extern void kprintf(const char *, ...);
  96.  
  97. //
  98. //    Forward function declarations
  99. //        Use unix style names (words separated by "_") for intercepts and callbacks
  100. //        Use Mac style names for internal functions (initial caps)
  101. //        Use ipk_ or ik_ prefix to avoid kernel name space conflicts
  102. //        ipk_ for PF_NKE and DLIL filter functions, ik_ for socket functions
  103. //
  104. // Tiger NKE socket intercepts
  105. static void ik_unregistered(sflt_handle handle);
  106. static errno_t ik_attach(void **cookie, socket_t so);
  107. static void    ik_detach(void *cookie, socket_t so);
  108. static void ik_notify(void *cookie, socket_t so, sflt_event_t event, void *param);
  109. static int ik_getpeername(void *cookie, socket_t so, struct sockaddr **sa);
  110. static int ik_getsockname(void *cookie, socket_t so, struct sockaddr **sa);
  111. static errno_t ik_data_in(void *cookie, socket_t so,
  112.                     const struct sockaddr *from, mbuf_t *data,
  113.                     mbuf_t *control, sflt_data_flag_t flags);
  114. static errno_t ik_data_out(void *cookie, socket_t so,
  115.                     const struct sockaddr *to, mbuf_t *data,
  116.                     mbuf_t *control, sflt_data_flag_t flags);
  117. static errno_t ik_connect_in(void *cookie, socket_t so, const struct sockaddr *from);
  118. static errno_t ik_connect_out(void *cookie, socket_t so, const struct sockaddr *to);
  119. static errno_t ik_bind(void *cookie, socket_t so, const struct sockaddr *to);
  120. static errno_t ik_setoption(void *cookie, socket_t so, sockopt_t opt);
  121. static errno_t ik_getoption(void *cookie, socket_t so, sockopt_t opt);
  122. static errno_t ik_listen(void *cookie, socket_t so);
  123. static errno_t ik_ioctl(void *cookie, socket_t so, u_int32_t request, const char* argp);
  124.  
  125. // Tiger socket filter module wide state
  126. static int registered = 0;
  127. static int unregistered_started = 0;
  128. static int unregistered_complete = 0;
  129.  
  130. // Dispatch vector for Tiger socket intercepts
  131. static struct sflt_filter ik_sflt_filter = {
  132.     IPNetMonitor_TNKE_Handle,
  133.     SFLT_PROG,
  134.     "com.sustworks.kext.IPNetMonitor_TNKE",
  135.     
  136.     ik_unregistered,
  137.     ik_attach,
  138.     ik_detach,
  139.     
  140.     ik_notify,
  141.     ik_getpeername,
  142.     ik_getsockname,
  143.     ik_data_in,
  144.     ik_data_out,
  145.     ik_connect_in,
  146.     ik_connect_out,
  147.     ik_bind,
  148.     ik_setoption,
  149.     ik_getoption,
  150.     ik_listen,
  151.     ik_ioctl
  152. };
  153.  
  154. // mutex lock for synchronizeing NKE data between kernel threads
  155. static lck_mtx_t *tnke_lock;
  156. static lck_grp_t *tnke_lock_grp = 0;
  157.  
  158. // Tiger protocol filter intercpets
  159. static errno_t ipk_ipf_input_func(caddr_t cookie, mbuf_t *data, int hlen, u_int8_t protocol);
  160. static errno_t ipk_ipf_output_func(caddr_t cookie, mbuf_t *data, ipf_pktopts_t options);
  161. static void ipk_ipf_detach_func(caddr_t cookie);
  162.  
  163. // Tiger interface filter intercepts
  164. static void ipk_iff_detached_func(
  165.     void* cookie, 
  166.     ifnet_t interface);
  167. static void ipk_iff_event_func(
  168.     void* cookie, 
  169.     ifnet_t interface, 
  170.     protocol_family_t protocol, 
  171.     const struct kev_msg *event_msg);
  172. static errno_t ipk_iff_input_func(
  173.     void*cookie, 
  174.     ifnet_t interface, 
  175.     protocol_family_t protocol, 
  176.     mbuf_t *data, 
  177.     char **frame_ptr);
  178. static errno_t ipk_iff_ioctl_func(
  179.     void*cookie,
  180.     ifnet_t interface,
  181.     protocol_family_t protocol, 
  182.     u_long ioctl_cmd,
  183.     void*ioctl_arg);
  184. static errno_t ipk_iff_output_func(
  185.     void*cookie,
  186.     ifnet_t interface,
  187.     protocol_family_t protocol, 
  188.     mbuf_t *data);
  189.     
  190. // internal support functions
  191. static int ik_connect(socket_t cso);
  192. static void ik_disconnect(socket_t cso);
  193.  
  194. static int ik_attachCount(int controlIndex);
  195. static int ik_controlCount(int attachIndex);
  196. static int ik_controlIndexForSocket(socket_t so);
  197. static int ik_emptyControlIndex();
  198. static int ik_attachIndexForName(char *inName);
  199. static int ik_emptyAttachIndex();
  200. static int ik_detachController(int controlIndex);
  201. static int ik_detachInterface(int attachIndex);
  202.  
  203. // timer callbacks
  204. static void ipk_timeout(void *cookie);
  205. static void ipk_periodical();
  206. // send message to controlling socket
  207. void PROJECT_sendMessage(socket_t ctl, ipk_message_t *message);
  208.  
  209. //
  210. // Global structures and data storage
  211. //
  212.  
  213. // timer Ref Count (firewall enabled)
  214. int32_t PROJECT_timerRefCount;
  215.     // ipk_timeout reschedules itself when PROJECT_timerRefCount>0
  216. int32_t PROJECT_timerPending;
  217.  
  218. //
  219. // Module wide variables (not exported)
  220. //
  221. static int ipk_initted = 0;
  222.  
  223.  
  224. //
  225. // Setup per instance structures and storage
  226. //
  227.  
  228. // maximum number of controllers and DLIL attachments use index values 1..n
  229. // 0 is reserved for "not found"
  230. //#define kMaxControl    8
  231. //#define kMaxAttach 8
  232.  
  233. // Array of controller instances
  234. control_t PROJECT_control[kMaxControl+1];
  235.  
  236. // Global Array of DLIL attach instances
  237. attach_t PROJECT_attach[kMaxAttach+1];
  238.  
  239.  
  240. #pragma mark -- Load and unload kernel extension
  241. //
  242. // Load and unload kernel extension
  243. //
  244. // ---------------------------------------------------------------------------------
  245. //    Ñ IPNetMonitor_TNKE_start
  246. // ---------------------------------------------------------------------------------
  247. kern_return_t IPNetMonitor_TNKE_start (kmod_info_t * ki, void * data)
  248. {
  249.     int returnValue = KERN_SUCCESS;
  250.     errno_t status;
  251.     lck_grp_attr_t *grp_attributes = 0;
  252.     lck_attr_t *lck_attributes = 0;
  253.     int i;
  254.     
  255.     printf("IPNetMonitor_TNKE has loaded!\n");
  256.  
  257.     // set up the tag value associated with this NKE to mark previously seen packets
  258.     status = mbuf_tag_id_find(MY_BUNDLE_ID, &gidtag);
  259.     if (status != 0) {
  260.         printf("IPNetRouter_TNKE_start: mbuf_tag_id_find failed %d\n", status);
  261.         return KERN_FAILURE;
  262.     }
  263.  
  264.     /* Allocate a mutex lock */
  265.     grp_attributes = lck_grp_attr_alloc_init();
  266.     lck_grp_attr_setdefault(grp_attributes);
  267.     tnke_lock_grp = lck_grp_alloc_init("IPNetMonitor_TNKE", grp_attributes);
  268.     lck_grp_attr_free(grp_attributes);
  269.     grp_attributes = 0;
  270.  
  271.     lck_attributes = lck_attr_alloc_init();
  272.     lck_attr_setdefault(lck_attributes);
  273.     lck_attr_setdebug(lck_attributes);
  274.  
  275.     tnke_lock = lck_mtx_alloc_init(tnke_lock_grp, lck_attributes);
  276.  
  277.     lck_attr_free(lck_attributes);
  278.     lck_attributes = 0;
  279.  
  280.     // mutex lock
  281.     PROJECT_lock();
  282.     do {
  283.         // already initialized?
  284.         if (ipk_initted) break;
  285.         
  286.         // initialize global storage
  287.         PROJECT_timerRefCount = 0;
  288.         PROJECT_timerPending = 0;
  289.         
  290.         // initialize our instance storage
  291.         for (i=0; i<=kMaxControl; i++) {
  292.             bzero(&PROJECT_control[i], sizeof(control_t));
  293.         }
  294.         for (i=0; i<=kMaxAttach; i++) {
  295.             bzero(&PROJECT_attach[i], sizeof(attach_t));
  296.         }
  297.                 
  298.         // register our NKE
  299.         status = sflt_register(&ik_sflt_filter, PF_INET,
  300.                       SOCK_DGRAM, IPPROTO_UDP);
  301.  
  302.         if (status != 0) {
  303.             printf("IPNetMonitor_TNKE_start: sflt_register failed %d\n", status);
  304.             returnValue = KERN_FAILURE;
  305.         } else {
  306.             registered++;
  307.             ipk_initted = 1;
  308.         }
  309.         
  310.     } while (FALSE);
  311.     // mutex unlock
  312.     PROJECT_unlock();
  313.  
  314.     return returnValue;
  315. }
  316.  
  317.  
  318. // ---------------------------------------------------------------------------------
  319. //    Ñ IPNetMonitor_TNKE_stop
  320. // ---------------------------------------------------------------------------------
  321. kern_return_t IPNetMonitor_TNKE_stop (kmod_info_t * ki, void * data) {
  322.     int returnValue = KERN_SUCCESS;
  323.     errno_t status;
  324.     int i;
  325.  
  326.     // mutex lock
  327.     PROJECT_lock();
  328.     do {
  329.         // if not initted
  330.         if (!ipk_initted) break;
  331.         
  332.         // unlink controllers and remove any DLIL attach instances
  333.         for (i=1; i<=kMaxControl; i++) {
  334.             if (PROJECT_control[i].ctl != 0) {
  335.                 ik_detachController(i);
  336.                 // tell any clients the socket has gone away
  337.                 // not sure how to do this, so just fail for now
  338.                 returnValue = KERN_FAILURE;    // fail until all sockets are disconnected
  339.                 break;
  340.             }
  341.         }
  342.         if (returnValue != 0) break;
  343.         
  344.         // remove any remaining attach instances (defensive)
  345.         for (i=1; i<=kMaxAttach; i++) {
  346.             if (PROJECT_attach[i].ifFilterRef || PROJECT_attach[i].ipFilterRef) {
  347.                 ik_detachInterface(i);
  348.             }
  349.         }
  350.         
  351.         // need to cancel any pending kernel callbacks (timeout)
  352.             // fortunately we don't normally unload and can warn the user
  353.             // not to unload while any tools are running
  354.         // force timer ref count to zero
  355.         if (PROJECT_timerRefCount || PROJECT_timerPending) {
  356.             bsd_untimeout(ipk_timeout, (void *)0);
  357.             PROJECT_timerRefCount = 0;
  358.         }
  359.         
  360.         // unplug our socket filter
  361.         if (unregistered_started == 0) {
  362.             status = sflt_unregister(ik_sflt_filter.sf_handle);
  363.             if (status != 0) {
  364.                 printf("IPNetMonitor_TNKE_stop: sflt_unregister failed %d\n", status);
  365.                 returnValue = KERN_FAILURE;
  366.             }
  367.             else {
  368.                 unregistered_started++;
  369.             }
  370.         } else if (unregistered_complete) {
  371.             returnValue = KERN_SUCCESS;
  372.             ipk_initted = 0;
  373.         } else {
  374.             printf("pass_sock_filt_stop: again\n");
  375.             returnValue = KERN_FAILURE;
  376.         }
  377.     } while (FALSE);
  378.     // mutex unlock
  379.     PROJECT_unlock();
  380.     
  381.     // release mutex lock
  382.     if (returnValue == KERN_SUCCESS) {
  383.         if (tnke_lock)
  384.             lck_mtx_free(tnke_lock, tnke_lock_grp);
  385.         if (tnke_lock_grp)
  386.             lck_grp_free(tnke_lock_grp);
  387.         tnke_lock = 0;
  388.         tnke_lock_grp = 0;
  389.     }
  390.     
  391.     if (returnValue == 0) printf("IPNetMonitor_TNKE has unloaded!\n");
  392.  
  393.     return returnValue;
  394. }
  395.  
  396. #pragma mark -- Tiger socket intercept functions --
  397.  
  398. static void 
  399. ik_unregistered(sflt_handle handle)
  400. {
  401.     unregistered_complete++;
  402.     return;
  403. }
  404.  
  405. static errno_t    
  406. ik_attach(void **cookie, socket_t so)
  407. {
  408.     printf("ik_attach: %x\n", so);
  409.     return 0;
  410. }
  411.  
  412. static void    
  413. ik_detach(void *cookie, socket_t so)
  414. {
  415.     printf("ik_detach: %x\n", so);
  416.     return;
  417. }
  418.  
  419. // this is where we get notified that a socket is closing
  420. static void ik_notify(void *cookie, socket_t so,
  421.                          sflt_event_t event, void *param)
  422. {
  423.     //printf("ik_notify: %x event: %lu\n", so, event);
  424.     if (event == sock_evt_closing) {
  425.         // socket is being closed:
  426.         //     disconnect, turn off monitoring, and detach from interface if no more references.
  427.         // - Any open sockets will be closed by the kernel when the process quits,
  428.         //   so this is our big chance to clean up properly regardless of how the
  429.         //   companion application died.
  430.         ik_disconnect(so);
  431.     }
  432.     return;
  433. }
  434.  
  435. static int
  436. ik_getpeername(void *cookie, socket_t so,
  437.                          struct sockaddr **sa)
  438. {
  439.     return 0;
  440. }
  441.  
  442. static int
  443. ik_getsockname(void *cookie, socket_t so,
  444.                          struct sockaddr **sa)
  445. {
  446.     return 0;
  447. }
  448.  
  449.  
  450. static errno_t    
  451. ik_data_in(void *cookie, socket_t so,
  452.                     const struct sockaddr *from, mbuf_t *data,
  453.                     mbuf_t *control, sflt_data_flag_t flags)
  454. {
  455.     return 0;
  456. }
  457.  
  458. static errno_t
  459. ik_data_out(void *cookie, socket_t so,
  460.                     const struct sockaddr *to, mbuf_t *data,
  461.                     mbuf_t *control, sflt_data_flag_t flags)
  462. {
  463.     return 0;
  464. }
  465.  
  466.  
  467. static errno_t
  468. ik_connect_in(void *cookie, socket_t so,
  469.                     const struct sockaddr *from)
  470. {
  471.     printf("ik_connect_in: %x\n", so);
  472.     return 0;
  473. }
  474.  
  475. static errno_t    
  476. ik_connect_out(void *cookie, socket_t so,
  477.                     const struct sockaddr *to)
  478. {
  479.     printf("ik_connect_in: %x\n", so);
  480.     return 0;
  481. }
  482.  
  483. static errno_t
  484.     ik_bind(void *cookie, socket_t so,
  485.                     const struct sockaddr *to)
  486. {
  487.     return 0;
  488. }
  489.  
  490. // ---------------------------------------------------------------------------------
  491. //    Ñ ik_setoption
  492. // ---------------------------------------------------------------------------------
  493. // intercept socket options (soset and soget)
  494. static errno_t
  495. ik_setoption(void *cookie, socket_t so, sockopt_t sopt)
  496. {
  497.     errno_t returnValue = 0;    // continue normall processing (pass it on)
  498.     errno_t status;
  499.     int controlIndex=0;
  500.     int attachIndex=0;
  501.  
  502.     do {
  503.         // find our controller instance
  504.         controlIndex = ik_controlIndexForSocket(so);
  505.         if (!controlIndex) {
  506.             // not yet connected, try to connect
  507.             returnValue = ik_connect(so);
  508.             if (returnValue != EJUSTRETURN) break;
  509.             controlIndex = ik_controlIndexForSocket(so);
  510.             if (!controlIndex) {
  511.                 returnValue = ENOTCONN;
  512.                 break;
  513.             }
  514.         }
  515.  
  516.         switch(sockopt_name(sopt)) {
  517.             case SO_ATTACH_LINK:
  518.                 // mutex lock
  519.                 PROJECT_lock();
  520.                 do {
  521.                     // attach a controller socket to an IP interface (data link)
  522.                     struct sopt_attachParam attachParam;
  523.                     // Reference: copyin and copyout option parameters
  524.                     //errno_t sockopt_copyin(sockopt_t sopt, void *data, size_t length);
  525.                     //errno_t sockopt_copyout(sockopt_t sopt, void *data, size_t length);
  526.                     #if IPK_DEBUG
  527.                         printf("ik_setoption: received SO_ATTACH_LINK\n");
  528.                     #endif
  529.                     // copyin option parameter
  530.                     returnValue = sockopt_copyin(sopt, &attachParam, sizeof(attachParam));
  531.                     if (returnValue) break;
  532.                     
  533.                     // look for existing DLIL attach by bsdName
  534.                     attachIndex = ik_attachIndexForName(attachParam.bsdName);
  535.                     if (attachIndex) {
  536.                         // found existing DLIL attach
  537.                         // associate this controller with DLIL attach
  538.                         PROJECT_control[controlIndex].attachMap[attachIndex] = 1;
  539.                         returnValue = EJUSTRETURN;
  540.                         break;            
  541.                     }                                    
  542.                     // did not find previous attachment
  543.                     // create a new DLIL attach instance for requested interface
  544.                             // find slot for attach instance
  545.                     attachIndex = ik_emptyAttachIndex();
  546.                     if (!attachIndex) {
  547.                         returnValue = EBUSY;
  548.                         break;
  549.                     }
  550.                     bzero(&PROJECT_attach[attachIndex], sizeof(attach_t));
  551.                     // remember our own index for convenience
  552.                     PROJECT_attach[attachIndex].attachIndex = attachIndex;
  553.                     
  554.                     if (attachParam.protocolFilter) {
  555.                         // Register IPv4 protocol filter
  556.                         struct ipf_filter ipf_filter;
  557.                         ipfilter_t ipFilterRef;
  558.                             // set cookie to point to this attach instance
  559.                         ipf_filter.cookie = (caddr_t)&PROJECT_attach[attachIndex];
  560.                         ipf_filter.name = "com.sustworks.nke.IPNetMonitor_TNKE";
  561.                         ipf_filter.ipf_input = (ipf_input_func)ipk_ipf_input_func;
  562.                         ipf_filter.ipf_output = (ipf_output_func)ipk_ipf_output_func;
  563.                         ipf_filter.ipf_detach = (ipf_detach_func)ipk_ipf_detach_func;
  564.                              // attach as IP filter
  565.                         returnValue = ipf_addv4(&ipf_filter, &ipFilterRef);
  566.                         PROJECT_attach[attachIndex].ipFilterRef = ipFilterRef;
  567.                         if (returnValue != 0) {
  568.                             printf("ik_setoption attach: ipf_addv4 failed %d\n", returnValue);
  569.                             break;
  570.                         } else {
  571.                             #if IPK_DEBUG
  572.                             printf("ik_setoption: protocol filter on %s\n", attachParam.bsdName);
  573.                             #endif
  574.                         }
  575.                     }
  576.                     else {
  577.                         // Register as interface filter
  578.                         ifnet_t ifnet_ref = NULL;
  579.                         struct iff_filter iff_filter;
  580.                         interface_filter_t ifFilterRef;
  581.                         // find matching ifnet for interface name (must call ifnet_release)
  582.                         returnValue = ifnet_find_by_name(attachParam.bsdName, &ifnet_ref);
  583.                         if (returnValue != 0) break;
  584.                             // set cookie to point to this attach instance
  585.                         iff_filter.iff_cookie = (caddr_t)&PROJECT_attach[attachIndex];
  586.                         iff_filter.iff_name = "com.sustworks.nke.IPNetMonitor_TNKE";
  587.                         iff_filter.iff_protocol = PF_INET;
  588.                         iff_filter.iff_input = ipk_iff_input_func;
  589.                         iff_filter.iff_output = ipk_iff_output_func;
  590.                         iff_filter.iff_event = ipk_iff_event_func;
  591.                         iff_filter.iff_ioctl = ipk_iff_ioctl_func;
  592.                         iff_filter.iff_detached = ipk_iff_detached_func;
  593.                         // attach as interface filter
  594.                         returnValue = iflt_attach(ifnet_ref, &iff_filter, &ifFilterRef);
  595.                         PROJECT_attach[attachIndex].ifFilterRef = ifFilterRef;
  596.                         // remember the ifnet we found (release when detaching)
  597.                         PROJECT_attach[attachIndex].ifnet_ref = ifnet_ref;
  598.                         //if (ifnet_ref) ifnet_release(ifnet_ref);
  599.                         if (returnValue != 0) {
  600.                             printf("ik_setoption attach: iflt_attached failed %d\n", returnValue);
  601.                             break;
  602.                         } else {
  603.                             #if IPK_DEBUG
  604.                             printf("ik_setoption: interface filter on %s\n", attachParam.bsdName);
  605.                             #endif
  606.                         }
  607.                     }
  608.  
  609.                     // remember other attach info
  610.                     {
  611.                         int len;
  612.                         // default to filter on
  613.                         PROJECT_attach[attachIndex].kftInterfaceEntry.filterOn = 1;
  614.                         // remember interface name as CString
  615.                         len = strlen(attachParam.bsdName);
  616.                         memcpy(&PROJECT_attach[attachIndex].kftInterfaceEntry.bsdName[0],
  617.                                         &attachParam.bsdName[0], len+1);
  618.                         // associate this controller with DLIL attach
  619.                         PROJECT_control[controlIndex].attachMap[attachIndex] = 1;
  620.                         #if IPK_DEBUG
  621.                                 printf("ik_setoption control instance: %d attach instance: %d\n",
  622.                                         controlIndex, attachIndex);
  623.                         #endif
  624.                     }
  625.                     // Everything worked, Yay!
  626.                     returnValue = EJUSTRETURN;                    
  627.                 } while (FALSE);
  628.                 // mutex unlock
  629.                 PROJECT_unlock();
  630.                 break;
  631.             case SO_DETACH_LINK:
  632.                 // mutex lock
  633.                 PROJECT_lock();
  634.                 do {
  635.                     // detach specified interface from controller socket
  636.                     struct sopt_attachParam attachParam;
  637.                     #if IPK_DEBUG
  638.                         printf("ik_setoption: received SO_DETACH_LINK\n");
  639.                     #endif
  640.                     // if name is nil, detach controller and any interface attachments
  641.                     if (sockopt_valsize(sopt) == 0) {
  642.                         #if IPK_DEBUG
  643.                             printf("ik_setoption detach all interfaces\n");
  644.                         #endif
  645.                         returnValue = ik_detachController(controlIndex);
  646.                         if (returnValue) break;
  647.                         returnValue = EJUSTRETURN;
  648.                         break;
  649.                     }
  650.                     // copyin option parameter
  651.                     returnValue = sockopt_copyin(sopt, &attachParam, sizeof(attachParam));
  652.                     if (returnValue) break;
  653.                     // make sure delay table is empty before detaching from any interfaces
  654.                     //KFT_delayAge(0);                
  655.                     // look for existing DLIL attach by bsdName
  656.                     attachIndex = ik_attachIndexForName(attachParam.bsdName);
  657.                     if (attachIndex) {
  658.                         // found existing DLIL attach
  659.                         // dis-associate this controller with attach
  660.                         PROJECT_control[controlIndex].attachMap[attachIndex] = 0;
  661.                         // are there any more references?
  662.                         if (ik_controlCount(attachIndex) == 0) {
  663.                             // no more references to this attach instance
  664.                             ik_detachInterface(attachIndex);
  665.                         }
  666.                     }
  667.                     else {
  668.                         returnValue = ENOENT;
  669.                         break;
  670.                     }
  671.                     returnValue = EJUSTRETURN;
  672.                 } while (FALSE);
  673.                 // mutex unlock
  674.                 PROJECT_unlock();
  675.                 break;
  676.             case SO_MONITOR_ON:
  677.                 do {
  678.                     #if IPK_DEBUG
  679.                         printf("ik_setoption: received SO_MONITOR_ON\n");
  680.                     #endif
  681.                     // reset nkeSends to tell NKE we want more
  682.                     PROJECT_control[controlIndex].nkeSends = 0;
  683.                     // check for attachment to an interface
  684.                     if (ik_attachCount(controlIndex) == 0) {
  685.                         returnValue = ENOENT;
  686.                         break;
  687.                     }
  688.                     // if monitoring is not already on
  689.                     if (PROJECT_control[controlIndex].monitorOn == 0) {
  690.                         int32_t result;
  691.                         PROJECT_control[controlIndex].monitorOn = 1;
  692.                         // start 1-second timer to send interface stats upstream
  693.                         //PROJECT_timerRefCount += 1;
  694.                         result = OSAddAtomic(1, (SInt32*)&PROJECT_timerRefCount);
  695.                         result = OSAddAtomic(1, (SInt32*)&PROJECT_timerPending);
  696.                         if (result == 0) {    // timer is not running
  697.                             #if IPK_DEBUG
  698.                                 printf("ik_setoption: start timer\n");
  699.                             #endif
  700.                             ipk_timeout((void *)0);
  701.                         }
  702.                     }
  703.                     returnValue = EJUSTRETURN;
  704.                 } while (FALSE);
  705.                 break;
  706.             case SO_MONITOR_OFF:
  707.                 do {
  708.                     #if IPK_DEBUG
  709.                         printf("ik_setoption: received SO_MONITOR_OFF\n");
  710.                     #endif
  711.                     PROJECT_control[controlIndex].monitorOn = 0;
  712.                     // bump timer ref count
  713.                     //PROJECT_timerRefCount -= 1;
  714.                     status = OSAddAtomic(-1, (SInt32*)&PROJECT_timerRefCount);
  715.                     if (status <= 0) PROJECT_timerRefCount = 0;    // defensive
  716.                     // report current connection table
  717.                     returnValue = EJUSTRETURN;
  718.                 } while (FALSE);
  719.                 break;
  720.             default: {
  721.                 #if IPK_DEBUG
  722.                     printf("ik_setoption: default unrecognized sopt->sopt_name=%x pass it on\n", sockopt_name(sopt));
  723.                 #endif
  724.                 returnValue = 0;
  725.                 break;
  726.             }
  727.         }    // end switch
  728.     } while (FALSE);
  729.     #if 0
  730.         printf("ik_setoption returnValue: %d\n", returnValue);
  731.     #endif    
  732.     return returnValue;
  733. }
  734.                     
  735. static errno_t
  736. ik_getoption(void *cookie, socket_t so,
  737.                     sockopt_t opt)
  738. {
  739.     return 0;
  740. }
  741.  
  742. static    errno_t
  743. ik_listen(void *cookie, socket_t so)
  744. {
  745.     return 0;
  746. }
  747.                  
  748.  
  749. static    errno_t
  750. ik_ioctl(void *cookie, socket_t so,
  751.                     u_int32_t request, const char* argp)
  752. {
  753.     return 0;
  754. }
  755.  
  756.  
  757. #pragma mark -- Tiger protocol filter intercept functions
  758. static errno_t 
  759. ipk_ipf_input_func(caddr_t cookie, mbuf_t *data, int hlen, u_int8_t protocol)
  760. {
  761.     int returnValue = 0;
  762.     attach_t* myAttach;
  763.     size_t len;
  764.  
  765.     // avoid duplicates
  766.     if ( PROJECT_is_mtag(*data, TAG_IN) ) return 0;
  767.     returnValue = PROJECT_mtag(*data, TAG_IN);
  768.     //if (returnValue != 0) return returnValue;    // if allocation failed, get out
  769.  
  770.     // get access to our attach instance
  771.     myAttach = (attach_t*)cookie;
  772.     
  773.     // Count whatever we get at this level.  Notice VPN might be counted twice.
  774.     //if (protocol != IPPROTO_ICMP && protocol != IPPROTO_TCP &&  protocol != IPPROTO_TCP) return 0;
  775.     
  776.     // count receive traffic
  777.     len = mbuf_pkthdr_len(*data);
  778.     //myAttach->receiveCount += len;
  779.     OSAddAtomic(len, (SInt32*)&myAttach->receiveCount);
  780.     
  781.     return returnValue;
  782. }
  783.  
  784. static errno_t 
  785. ipk_ipf_output_func(caddr_t cookie, mbuf_t *data, ipf_pktopts_t options)
  786. {
  787.     int returnValue = 0;
  788.     attach_t* myAttach;
  789.     size_t len;
  790.  
  791.     // avoid duplicates
  792.     if ( PROJECT_is_mtag(*data, TAG_OUT) ) return 0;
  793.     returnValue = PROJECT_mtag(*data, TAG_OUT);
  794.     //if (returnValue != 0) return returnValue;    // if allocation failed, get out
  795.  
  796.     // get access to our attach instance
  797.     myAttach = (attach_t*)cookie;
  798.     
  799.     // Count whatever we get at this level.  Notice VPN might be counted twice.
  800.     //if (protocol != IPPROTO_ICMP && protocol != IPPROTO_TCP &&  protocol != IPPROTO_TCP) return 0;
  801.     
  802.     // count receive traffic
  803.     len = mbuf_pkthdr_len(*data);
  804.     //myAttach->sendCount += len;
  805.     OSAddAtomic(len, (SInt32*)&myAttach->sendCount);
  806.     
  807.     return returnValue;
  808. }
  809.  
  810. static void 
  811. ipk_ipf_detach_func(caddr_t cookie)
  812. {
  813.     //printf("ipk_ipf_detach_func: %x\n", *(ipfilter_t*)cookie);
  814. }
  815.  
  816. #pragma mark -- Tiger interface filter intercept functions
  817.  
  818. static void ipk_iff_detached_func(
  819.     void *cookie, 
  820.     ifnet_t interface)
  821. {
  822.  
  823. static void ipk_iff_event_func(
  824.     void *cookie, 
  825.     ifnet_t interface, 
  826.     protocol_family_t protocol, 
  827.     const struct kev_msg *event_msg)
  828. {
  829.     // check for interface detaching event
  830.     if (event_msg->event_code == KEV_DL_IF_DETACHING) {
  831.         attach_t* myAttach;
  832.         u_int8_t attachIndex;
  833.         // get access to our attach instance
  834.         myAttach = (attach_t*)cookie;
  835.         attachIndex = myAttach->attachIndex;
  836.         // make sure interface is detached
  837.         if (PROJECT_attach[attachIndex].ifnet_ref) {
  838.             PROJECT_lock();
  839.             ik_detachInterface(attachIndex);
  840.             PROJECT_unlock();
  841.         }
  842.     }
  843. }
  844.  
  845. static errno_t ipk_iff_input_func(
  846.     void *cookie, 
  847.     ifnet_t interface, 
  848.     protocol_family_t protocol, 
  849.     mbuf_t *data, 
  850.     char **frame_ptr)
  851. {
  852.     int returnValue = 0;
  853.     attach_t* myAttach;
  854.     int32_t len;
  855.  
  856.     // avoid duplicates
  857.     if ( PROJECT_is_mtag(*data, TAG_IN) ) return 0;
  858.     returnValue = PROJECT_mtag(*data, TAG_IN);
  859.     //if (returnValue != 0) return returnValue;    // if allocation failed, get out
  860.     
  861.     // get access to our attach instance
  862.     myAttach = (attach_t*)cookie;
  863.     
  864.     // Count whatever we get at this level.  Notice VPN might be counted twice.
  865.     //if (protocol != IPPROTO_ICMP && protocol != IPPROTO_TCP &&  protocol != IPPROTO_TCP) return 0;
  866.     
  867.     // count receive traffic
  868.     len = mbuf_pkthdr_len(*data);
  869. //    myAttach->receiveCount += len;
  870.     OSAddAtomic(len, (SInt32*)&myAttach->receiveCount);
  871.     
  872.     return returnValue;
  873. }
  874.  
  875. static errno_t ipk_iff_ioctl_func(
  876.     void *cookie,
  877.     ifnet_t interface,
  878.     protocol_family_t protocol, 
  879.     u_long ioctl_cmd,
  880.     void* ioctl_arg)
  881. {
  882.     return EOPNOTSUPP;
  883. }
  884.  
  885. static errno_t ipk_iff_output_func(
  886.     void *cookie,
  887.     ifnet_t interface,
  888.     protocol_family_t protocol, 
  889.     mbuf_t *data)
  890. {
  891.     int returnValue = 0;
  892.     attach_t* myAttach;
  893.     int32_t len;
  894.  
  895.     // avoid duplicates
  896.     if ( PROJECT_is_mtag(*data, TAG_OUT) ) return 0;
  897.     returnValue = PROJECT_mtag(*data, TAG_OUT);
  898.     //if (returnValue != 0) return returnValue;    // if allocation failed, get out
  899.  
  900.     // get access to our attach instance
  901.     myAttach = (attach_t*)cookie;
  902.  
  903.     int headerLen =  ifnet_hdrlen(interface);
  904.     // fix header to work around PPP bug
  905.     if (ifnet_type(interface) == IFT_PPP) {
  906.         // fix header to work around PPP bug
  907.         //if ((m->m_data[headerLength-2] & 0xF0) == 0x40) headerLength -= 2;
  908.         u_int8_t* dp = mbuf_data(*data);
  909.         if ((dp[headerLen-2] & 0xF0) == 0x40) headerLen -= 2;
  910.     }
  911.  
  912.     // Count whatever we get at this level.    
  913.     // count receive traffic
  914.     len = mbuf_pkthdr_len(*data) - headerLen;
  915. //    myAttach->sendCount += len;
  916.     OSAddAtomic(len, (SInt32*)&myAttach->sendCount);
  917.     
  918.     return returnValue;
  919. }
  920.  
  921. #pragma mark -- NKE support functions --
  922. #pragma mark does mutex lock
  923.  
  924. // ---------------------------------------------------------------------------------
  925. //    Ñ PROJECT_lock
  926. // ---------------------------------------------------------------------------------
  927. void PROJECT_lock()
  928. {
  929.     // lock to allow one thread at a time
  930.     lck_mtx_lock(tnke_lock);
  931. }
  932. // ---------------------------------------------------------------------------------
  933. //    Ñ PROJECT_unlock
  934. // ---------------------------------------------------------------------------------
  935. void PROJECT_unlock()
  936. {
  937.     // unlock
  938.     lck_mtx_unlock(tnke_lock);
  939. }
  940.  
  941. // ---------------------------------------------------------------------------------
  942. //    Ñ ik_connect
  943. // ---------------------------------------------------------------------------------
  944. //    Register connection between controller socket and our NKE
  945. //    Called via PF_NKE, ik_setoption (set_SO) and also soconnect (standard UDP)
  946. static int ik_connect(socket_t cso)
  947. {
  948.     int returnValue = 0;
  949.     int controlIndex;
  950. #if IPK_DEBUG
  951.             printf("ik_connect\n");
  952. #endif
  953.     // mutex lock
  954.     PROJECT_lock();
  955.  
  956.     do {
  957.         // check if this controller socket is already connected
  958.         controlIndex = ik_controlIndexForSocket(cso);
  959.         if (controlIndex) {    // found it
  960.             returnValue = EISCONN;
  961.             break;
  962.         }
  963.  
  964.         // find slot for connection instance
  965.         controlIndex = ik_emptyControlIndex();
  966.         if (!controlIndex) {
  967.             returnValue = EBUSY;
  968.             break;        // all connection slots full
  969.         }
  970.         // register we have a connection
  971.         PROJECT_control[controlIndex].ctl = cso;
  972.         returnValue = EJUSTRETURN;
  973.     } while (FALSE);
  974.  
  975.     // mutex unlock
  976.     PROJECT_unlock();
  977.     
  978.     return returnValue;
  979. }
  980.  
  981.  
  982. // ---------------------------------------------------------------------------------
  983. //    Ñ ik_disconnect
  984. // ---------------------------------------------------------------------------------
  985. static void ik_disconnect(socket_t cso)
  986. {
  987.     int controlIndex;
  988.  
  989.     #if IPK_DEBUG
  990.         printf("ik_disconnect\n");
  991.     #endif
  992.     // mutex lock
  993.     PROJECT_lock();
  994.     
  995.     // check if this controller socket is connected and remove it
  996.     controlIndex = ik_controlIndexForSocket(cso);
  997.     if (controlIndex) {    // found it
  998.         // remove reference to attach instance and clear control instance
  999.         ik_detachController(controlIndex);
  1000.     }
  1001.     
  1002.     // mutex unlock
  1003.     PROJECT_unlock();
  1004. }
  1005.  
  1006. // ---------------------------------------------------------------------------------
  1007. //    Ñ ipk_timeout
  1008. // ---------------------------------------------------------------------------------
  1009. //    one second timer used for monitoring
  1010. //    reschedules itself to be called each second when timerRefCount > 0
  1011. static void ipk_timeout(void *cookie)
  1012. {
  1013.     struct timespec ts;    
  1014.     ts.tv_sec = 1;        // one second interval
  1015.     ts.tv_nsec = 0;
  1016.     // lock to allow one thread at a time
  1017.     PROJECT_lock();
  1018.  
  1019.     ipk_periodical();
  1020.     // reschedule ourself if anyone needs us
  1021.         // timeout(void (*func)(), void *cookie, int ticks);
  1022.     if (PROJECT_timerRefCount > 0) {
  1023.         PROJECT_timerPending = TRUE;
  1024.         bsd_timeout(ipk_timeout, (void *)0, &ts);
  1025.     }
  1026.     else {
  1027.         PROJECT_timerPending = FALSE;
  1028.         #if IPK_DEBUG
  1029.             printf("ipk_timeout: stop timer\n");
  1030.         #endif
  1031.     }
  1032.     // unlock
  1033.     PROJECT_unlock();
  1034. }
  1035.  
  1036. #pragma mark no mutex lock (caller must have it)
  1037. // ---------------------------------------------------------------------------------
  1038. //    Ñ ipk_periodical
  1039. // ---------------------------------------------------------------------------------
  1040. //    periodic processing
  1041. static void ipk_periodical()
  1042. {
  1043.     int i, j;
  1044.     // grab stats for each attach instance
  1045.     for (i=1; i<=kMaxAttach; i++) {
  1046.         if (PROJECT_attach[i].ipFilterRef || PROJECT_attach[i].ifFilterRef) {
  1047.             // copy current value
  1048.             PROJECT_attach[i].sendStamp = PROJECT_attach[i].sendCount;
  1049.             PROJECT_attach[i].receiveStamp = PROJECT_attach[i].receiveCount;
  1050.             // reset counter
  1051.             PROJECT_attach[i].sendCount = 0;
  1052.             PROJECT_attach[i].receiveCount = 0;
  1053.         }
  1054.     }    
  1055.  
  1056.     // send corresponding stats upstream for each monitoring control instance
  1057.     for (i=1; i<=kMaxControl; i++) {
  1058.         if (PROJECT_control[i].monitorOn) {
  1059.             // increment NKE sends since last request so we don't
  1060.             // flood input queue when no one is listening.
  1061.             PROJECT_control[i].nkeSends += 1;
  1062.             if (PROJECT_control[i].nkeSends < 15) {        // 15 seconds of data max
  1063.                 // build message to send monitor stats
  1064.                 ipk_monitorStats_t    monitorStats;
  1065.                 monitorStats.length = sizeof(ipk_monitorStats_t);
  1066.                 monitorStats.type = kMonitorStats;
  1067.                 for (j=1; j<=kMaxAttach; j++) {
  1068.                     if (PROJECT_control[i].attachMap[j]) {
  1069.                         monitorStats.sendCount = PROJECT_attach[j].sendStamp;
  1070.                         monitorStats.receiveCount = PROJECT_attach[j].receiveStamp;
  1071.                         break;
  1072.                     }
  1073.                 }
  1074.                 // send it
  1075.                 PROJECT_sendMessage(PROJECT_control[i].ctl, (ipk_message_t*)&monitorStats);
  1076.             }
  1077.         }
  1078.     }
  1079. }
  1080.  
  1081.  
  1082.  
  1083. // ---------------------------------------------------------------------------------
  1084. //    Ñ PROJECT_sendMessageToAll
  1085. // ---------------------------------------------------------------------------------
  1086. //     send message to each active controller
  1087. void PROJECT_sendMessageToAll(ipk_message_t *message)
  1088. {
  1089.     int i;
  1090.     for (i=1;i<=kMaxControl;i++) {
  1091.         if (PROJECT_control[i].ctl) {
  1092.             // increment NKE sends since last request so we don't
  1093.             // keep flooding input queue when no one is listening.
  1094.             PROJECT_control[i].nkeSends += 1;
  1095.             if (PROJECT_control[i].nkeSends < 250) {        // max messages allowed in 2.5 seconds
  1096.                 PROJECT_sendMessage(PROJECT_control[i].ctl, message);
  1097.             }
  1098.         }
  1099.     }
  1100. }
  1101.  
  1102. // ---------------------------------------------------------------------------------
  1103. //    Ñ PROJECT_sendMessage
  1104. // ---------------------------------------------------------------------------------
  1105. //     send message to controlling socket
  1106. //  assumes caller has mutex lock
  1107. void PROJECT_sendMessage(socket_t ctl, ipk_message_t *message)
  1108. {
  1109.     struct sockaddr from;
  1110.     mbuf_t mbuf;
  1111.     errno_t status;
  1112.     
  1113.     do {
  1114.         void* dp;            // pointer to actual mbuf data
  1115.         size_t size;
  1116.         if (!ctl) break;    // defensive
  1117.         
  1118.         // setup from address
  1119.         bzero(&from, 16);
  1120.         from.sa_len = 16;
  1121.         from.sa_family = PF_INET;
  1122.         
  1123.         // get mbuf with cluster to hold our message
  1124.         status = mbuf_getpacket(MBUF_DONTWAIT, &mbuf);
  1125.         if (status != 0) break;
  1126.         
  1127.         status = mbuf_settype(mbuf, MBUF_TYPE_DATA);
  1128.         
  1129.         // confirm we have enough space for message
  1130.         size = mbuf_maxlen(mbuf);
  1131.         if (message->length > size) {
  1132.             mbuf_freem(mbuf);
  1133.             printf("sendMessage: mbuf too small for message\n");
  1134.             break;
  1135.         }
  1136.         // copy data to cluster
  1137.         dp = mbuf_datastart(mbuf);
  1138.         bcopy(message, dp, message->length);
  1139.         // set data and length
  1140.         status = mbuf_setdata(mbuf, dp, message->length);
  1141.         if (status != 0) {
  1142.             mbuf_freem(mbuf);
  1143.             printf("mbuf_setData: failed %d\n",status);
  1144.             break;
  1145.         }
  1146.         
  1147.         // inject data to socket
  1148.         status = sock_inject_data_in(
  1149.             ctl,
  1150.             &from, 
  1151.             mbuf,
  1152.             NULL,
  1153.             sock_data_filt_flag_record);
  1154.             
  1155.         if (status != 0) {
  1156.             mbuf_freem(mbuf);
  1157.             printf("sock_inject_data_in: failed %d\n",status);
  1158.             break;
  1159.         }
  1160.  
  1161.     } while (FALSE);
  1162. }
  1163.  
  1164. // ---------------------------------------------------------------------------------
  1165. //    Ñ ik_attachCount
  1166. // ---------------------------------------------------------------------------------
  1167. // how many attachments does this controller reference
  1168. static int ik_attachCount(int controlIndex)
  1169. {
  1170.     int count, i;
  1171.     count = 0;
  1172.     // valid controlIndex?
  1173.     if ((controlIndex > 0) && (controlIndex <= kMaxControl)) {
  1174.         // for each attach instance
  1175.         for (i=1; i<=kMaxAttach; i++) {
  1176.             // does this controller reference it
  1177.             if (PROJECT_control[controlIndex].attachMap[i]) count += 1;
  1178.         }
  1179.     }
  1180.     return count;    
  1181. }
  1182.  
  1183. // ---------------------------------------------------------------------------------
  1184. //    Ñ ik_controlCount
  1185. // ---------------------------------------------------------------------------------
  1186. // how many controllers reference this attachment
  1187. static int ik_controlCount(int attachIndex)
  1188. {
  1189.     int count, i;
  1190.     count = 0;
  1191.     // valid attachIndex?
  1192.     if ((attachIndex > 0) && (attachIndex <= kMaxAttach)) {
  1193.         // for each control instance
  1194.         for (i=1; i<=kMaxControl; i++) {
  1195.             // does it reference this attach instance
  1196.             if (PROJECT_control[i].attachMap[attachIndex]) count += 1;
  1197.         }
  1198.     }
  1199.     return count;
  1200. }
  1201.  
  1202. // ---------------------------------------------------------------------------------
  1203. //    Ñ ik_controlIndexForSocket
  1204. // ---------------------------------------------------------------------------------
  1205. //    Find controller instance with corresponding socket if any and pass back it's index.
  1206. //    Returns 0 for not found
  1207. static int ik_controlIndexForSocket(socket_t so)
  1208. {
  1209.     int returnValue = 0;        // controller not connected ENOTCONN
  1210.     int i;
  1211.     
  1212.     for (i=1; i<=kMaxControl; i++) {
  1213.         if (PROJECT_control[i].ctl == so) {
  1214.             returnValue = i;
  1215.             break;
  1216.         }
  1217.     }
  1218.     return returnValue;
  1219. }
  1220.  
  1221.  
  1222. // ---------------------------------------------------------------------------------
  1223. //    Ñ ik_emptyControlIndex
  1224. // ---------------------------------------------------------------------------------
  1225. //    Find an empty controller instance (available slot)
  1226. //    Returns 0 for not found
  1227. static int ik_emptyControlIndex()
  1228. {
  1229.     int returnValue = 0;        // all slots in use EBUSY
  1230.     int i;
  1231.     
  1232.     for (i=1; i<=kMaxControl; i++) {
  1233.         if (PROJECT_control[i].ctl == 0) {
  1234.             returnValue = i;
  1235.             break;
  1236.         }
  1237.     }
  1238.     return returnValue;
  1239. }
  1240.  
  1241. // ---------------------------------------------------------------------------------
  1242. //    Ñ ik_attachIndexForName
  1243. // ---------------------------------------------------------------------------------
  1244. //    Find attach instance with corresponding bsdName.
  1245. //    Return 0 for not found.
  1246. static int ik_attachIndexForName(char *inName)
  1247. {
  1248.     int returnValue = 0;    // no such entry ENOENT
  1249.     int i;
  1250.     int len;
  1251.     
  1252.     len = strlen(inName);
  1253.     for (i=1; i<=kMaxAttach; i++) {
  1254.         if ( memcmp(inName, &PROJECT_attach[i].kftInterfaceEntry.bsdName[0], len) == 0 ) {
  1255.             returnValue = i;
  1256.             break;
  1257.         }
  1258.     }
  1259.     return returnValue;
  1260. }
  1261.  
  1262. // ---------------------------------------------------------------------------------
  1263. //    Ñ ik_emptyAttachIndex
  1264. // ---------------------------------------------------------------------------------
  1265. //    Find an empty attach instance (available slot)
  1266. //    Return 0 for not found
  1267. static int ik_emptyAttachIndex()
  1268. {
  1269.     int returnValue = 0;    // all slots in use EBUSY
  1270.     int i;
  1271.     
  1272.     for (i=1; i<=kMaxAttach; i++) {
  1273.         if ((PROJECT_attach[i].ipFilterRef == 0) && (PROJECT_attach[i].ifFilterRef == 0)) {
  1274.             returnValue = i;
  1275.             break;
  1276.         }
  1277.     }
  1278.     return returnValue;
  1279. }
  1280.  
  1281. // ---------------------------------------------------------------------------------
  1282. //    Ñ ik_detachController
  1283. // ---------------------------------------------------------------------------------
  1284. //    detach controller and remove any interface attachments
  1285. //    that are no longer referenced.  Finally, clear the control instance.
  1286. //
  1287. //    return 0 for success or unix error code
  1288. static int ik_detachController(int controlIndex)
  1289. {
  1290.     int returnValue=0;
  1291.     int attachIndex;
  1292.     int result;
  1293.     do {
  1294.         if (!controlIndex) break;    // no control instance, we're done
  1295.         // make sure delay table is empty before detaching from any interfaces
  1296.         //KFT_delayAge(0);                
  1297.         // if controller was monitoring, turn it off
  1298.         // - user might quit app without stopping or closing monitor window
  1299.         if (PROJECT_control[controlIndex].monitorOn) {
  1300.             PROJECT_control[controlIndex].monitorOn = 0;
  1301.             // bump timer ref count
  1302.             //PROJECT_timerRefCount -= 1;
  1303.             //if (PROJECT_timerRefCount < 0) PROJECT_timerRefCount = 0;
  1304.             result = OSAddAtomic(-1, (SInt32*)&PROJECT_timerRefCount);
  1305.             if (result <= 0) PROJECT_timerRefCount = 0;    // defensive
  1306.         }
  1307.         // get corresponding attach instances
  1308.         for (attachIndex=1;attachIndex<=kMaxAttach;attachIndex++) {
  1309.             if (PROJECT_control[controlIndex].attachMap[attachIndex]) {
  1310.                 // remove our reference to attach instance
  1311.                 PROJECT_control[controlIndex].attachMap[attachIndex] = 0;            
  1312.                 // are there any more references?
  1313.                 if (ik_controlCount(attachIndex) == 0) {
  1314.                     // no more references to this attach instance
  1315.                     // detach our NKE from this interface and clear instance
  1316.                     if (PROJECT_attach[attachIndex].ifFilterRef || PROJECT_attach[attachIndex].ipFilterRef) {
  1317.                         ik_detachInterface(attachIndex);
  1318.                     }
  1319.                 }
  1320.             }    // end found attach instance
  1321.         }    // end for each attach instance
  1322.         // clear control instance
  1323.         bzero(&PROJECT_control[controlIndex], sizeof(control_t));
  1324.     } while (FALSE);
  1325.     return returnValue;
  1326. }
  1327.  
  1328.  
  1329. // ---------------------------------------------------------------------------------
  1330. //    Ñ ik_detachInterface
  1331. // ---------------------------------------------------------------------------------
  1332. //    detach interface and clear the attach instance
  1333. //    return 0 for success or unix error code
  1334. static int ik_detachInterface(int attachIndex)
  1335. {
  1336.     int returnValue=0;
  1337.     errno_t status;
  1338.     int i;
  1339.     do {
  1340.         if ((attachIndex == 0) || (attachIndex > kMaxAttach)) break;    // no attach instance, we're done
  1341.         // for each control instance
  1342.         for (i=1; i<=kMaxControl; i++) {
  1343.             // dis-associate with this attach instance
  1344.             PROJECT_control[i].attachMap[attachIndex] = 0;
  1345.         }
  1346.         // detach our NKE from this interface and clear instance
  1347.             // ifnet_ref
  1348.             // release and set to zero before dlil_detach_filter which calls ipk_ipf_detach_func
  1349.         if (PROJECT_attach[attachIndex].ifnet_ref) ifnet_release(PROJECT_attach[attachIndex].ifnet_ref);
  1350.         PROJECT_attach[attachIndex].ifnet_ref = 0;
  1351.             // ifFilterRef
  1352.         if (PROJECT_attach[attachIndex].ifFilterRef) iflt_detach(PROJECT_attach[attachIndex].ifFilterRef);
  1353.             // ipFilterRef
  1354.         if (PROJECT_attach[attachIndex].ipFilterRef) {
  1355.             status = ipf_remove(PROJECT_attach[attachIndex].ipFilterRef);
  1356.             if (status) {
  1357.                 printf("ik_detachInterface: ipf_remove failed %d\n", status);
  1358.                 returnValue = KERN_FAILURE;
  1359.             }
  1360.         }
  1361.         bzero(&PROJECT_attach[attachIndex], sizeof(attach_t));
  1362.     } while (0);
  1363.     return returnValue;
  1364. }
  1365.  
  1366. // ---------------------------------------------------------------------------------
  1367. //    Ñ PROJECT_mtag
  1368. // ---------------------------------------------------------------------------------
  1369. // Tag this packet with "tag_value" so we'll know if we have seen it.
  1370. // tag_value should be either TAG_IN or TAG_OUT.
  1371. //
  1372. // Notice if an mbuf is re-used to send a response such as an echo request (ping) that
  1373. // is converted to an echo reply, you may want to recognize the redirected mbuf as a new packet.
  1374. // Thus we distinguish TAG_IN from TAG_OUT and intentionally replace the
  1375. // previous tag value rather than combining.  If we re-direct a packet, we need to
  1376. // re-tag it accordingly. The code below checks for an existing tag and resets the value.
  1377. //
  1378. // Finally, an mbuf tag is effectively another mbuf that travels with the packet.
  1379. // Allocating an mbuf tag can fail in which case we return the corresponding error code.
  1380. // Notice it is the callers responsibility to free the original packet to avoid looping
  1381. // or a recursive lock attempt (kernel panic) if a packet without the correct
  1382. // tag is re-injected and processed again.
  1383. //
  1384. errno_t PROJECT_mtag(mbuf_t mbuf_ref, int tag_value)
  1385. {
  1386.     errno_t status;
  1387.     int *tag_ref;
  1388.     size_t len;
  1389.     // look for existing tag
  1390.     status = mbuf_tag_find(mbuf_ref, gidtag, MY_TAG_TYPE, &len, (void*)&tag_ref);
  1391.     // allocate tag if needed
  1392.     if (status != 0) {
  1393.         status = mbuf_tag_allocate(mbuf_ref, gidtag, MY_TAG_TYPE, sizeof(*tag_ref), MBUF_DONTWAIT, (void**)&tag_ref);
  1394.     }
  1395.     if (status == 0) *tag_ref = tag_value;
  1396.     return status;
  1397. }
  1398.  
  1399. // ---------------------------------------------------------------------------------
  1400. //    Ñ PROJECT_is_mtag
  1401. // ---------------------------------------------------------------------------------
  1402. // Return 1 if packet is tagged with "tag_value", otherwise 0
  1403. int PROJECT_is_mtag(mbuf_t mbuf_ref, int tag_value)
  1404. {
  1405.     int returnValue = 0;
  1406.     errno_t status;
  1407.     int *tag_ref;
  1408.     size_t len;
  1409.     // Check whether we have seen this packet before.
  1410.     status = mbuf_tag_find(mbuf_ref, gidtag, MY_TAG_TYPE, &len, (void**)&tag_ref);
  1411.     if ((status == 0) && (*tag_ref & tag_value)) returnValue = 1;
  1412.     return returnValue;
  1413. }
  1414.  
  1415.