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

  1. //
  2. //  IPNetSentry_TNKE.c
  3. //  Mac OS X Interface Filter NKE
  4. //
  5. //  Created by psichel [PAS] on Teus Nov 12 2002.
  6. //  Based on SharedIP and TCPLogger provided as Open Source sample code
  7. //    from Apple Computer.
  8. //
  9. //    See IPNetSentry_TNKE.h for high level design overview.
  10. //    You can send comments or suggestions to psichel@sustworks.com
  11. //    The companion IPNetSentryX 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 DEBUG_IPK 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 "IPNetSentry_TNKE.h"
  84. #include "IPTypes.h"
  85. #include "kft.h"
  86. #include "kftDelay.h"
  87. #include "kftTrigger.h"
  88. #include "kftConnectionTable.h"
  89. #ifdef IPNetRouter
  90. #include "kftPortMapTable.h"
  91. #include "kftNatTable.h"
  92. #endif
  93. #include "FilterTypes.h"
  94.  
  95. // tag packets so we can recognize re-injected ones
  96. #define MY_BUNDLE_ID "com.sustworks.kext.IPNetSentry_TNKE"
  97. #define MY_TAG_TYPE 1
  98. // tag associated with this kext for use in marking packets that have been previously processed
  99. static mbuf_tag_id_t    gidtag;
  100.  
  101. int     memcmp(const void *, const void *, size_t);
  102.  
  103. // macro to convert kernel to external socket
  104. //#define sotoextcb(so) (struct kextcb *)(so->so_ext)
  105.  
  106. //extern void kprintf(const char *, ...);
  107.  
  108. //
  109. //    Forward function declarations
  110. //        Use unix style names (words separated by "_") for intercepts and callbacks
  111. //        Use Mac style names for internal functions (initial caps)
  112. //        Use ipk_ or ik_ prefix to avoid kernel name space conflicts
  113. //        ipk_ for PF_NKE and DLIL filter functions, ik_ for socket functions
  114. //
  115. // Tiger NKE socket intercepts
  116. static void ik_unregistered(sflt_handle handle);
  117. static errno_t ik_attach(void **cookie, socket_t so);
  118. static void    ik_detach(void *cookie, socket_t so);
  119. static void ik_notify(void *cookie, socket_t so, sflt_event_t event, void *param);
  120. static int ik_getpeername(void *cookie, socket_t so, struct sockaddr **sa);
  121. static int ik_getsockname(void *cookie, socket_t so, struct sockaddr **sa);
  122. static errno_t ik_data_in(void *cookie, socket_t so,
  123.                     const struct sockaddr *from, mbuf_t *data,
  124.                     mbuf_t *control, sflt_data_flag_t flags);
  125. static errno_t ik_data_out(void *cookie, socket_t so,
  126.                     const struct sockaddr *to, mbuf_t *data,
  127.                     mbuf_t *control, sflt_data_flag_t flags);
  128. static errno_t ik_connect_in(void *cookie, socket_t so, const struct sockaddr *from);
  129. static errno_t ik_connect_out(void *cookie, socket_t so, const struct sockaddr *to);
  130. static errno_t ik_bind(void *cookie, socket_t so, const struct sockaddr *to);
  131. static errno_t ik_setoption(void *cookie, socket_t so, sockopt_t opt);
  132. static errno_t ik_getoption(void *cookie, socket_t so, sockopt_t opt);
  133. static errno_t ik_listen(void *cookie, socket_t so);
  134. static errno_t ik_ioctl(void *cookie, socket_t so, u_int32_t request, const char* argp);
  135.  
  136. // Tiger socket filter module wide state
  137. static int registered = 0;
  138. static int unregistered_started = 0;
  139. static int unregistered_complete = 0;
  140.  
  141. // Dispatch vector for Tiger socket intercepts
  142. static struct sflt_filter ik_sflt_filter = {
  143.     IPNetSentry_TNKE_Handle,
  144.     SFLT_PROG,
  145.     "com.sustworks.kext.IPNetSentry_TNKE",
  146.     
  147.     ik_unregistered,
  148.     ik_attach,
  149.     ik_detach,
  150.     
  151.     ik_notify,
  152.     ik_getpeername,
  153.     ik_getsockname,
  154.     ik_data_in,
  155.     ik_data_out,
  156.     ik_connect_in,
  157.     ik_connect_out,
  158.     ik_bind,
  159.     ik_setoption,
  160.     ik_getoption,
  161.     ik_listen,
  162.     ik_ioctl
  163. };
  164.  
  165. // mutex lock for synchronizeing NKE data between kernel threads
  166. static lck_mtx_t *tnke_lock;
  167. static lck_grp_t *tnke_lock_grp = 0;
  168.  
  169. // Tiger protocol filter intercpets
  170. static errno_t ipk_ipf_input_func(caddr_t cookie, mbuf_t *data, int hlen, u_int8_t protocol);
  171. static errno_t ipk_ipf_output_func(caddr_t cookie, mbuf_t *data, ipf_pktopts_t options);
  172. static void ipk_ipf_detach_func(caddr_t cookie);
  173.  
  174. // Tiger interface filter intercepts
  175. static void ipk_iff_detached_func(
  176.     void* cookie, 
  177.     ifnet_t interface);
  178. static void ipk_iff_event_func(
  179.     void* cookie, 
  180.     ifnet_t interface, 
  181.     protocol_family_t protocol, 
  182.     const struct kev_msg *event_msg);
  183. static errno_t ipk_iff_input_func(
  184.     void*cookie, 
  185.     ifnet_t interface, 
  186.     protocol_family_t protocol, 
  187.     mbuf_t *data, 
  188.     char **frame_ptr);
  189. static errno_t ipk_iff_ioctl_func(
  190.     void*cookie,
  191.     ifnet_t interface,
  192.     protocol_family_t protocol, 
  193.     u_long ioctl_cmd,
  194.     void*ioctl_arg);
  195. static errno_t ipk_iff_output_func(
  196.     void*cookie,
  197.     ifnet_t interface,
  198.     protocol_family_t protocol, 
  199.     mbuf_t *data);
  200.     
  201. // internal support functions
  202. static int ik_connect(socket_t cso);
  203. static void ik_disconnect(socket_t cso);
  204.  
  205. static int ik_attachCount(int controlIndex);
  206. static int ik_controlCount(int attachIndex);
  207. static int ik_controlIndexForSocket(socket_t so);
  208. static int ik_emptyControlIndex();
  209. static int ik_attachIndexForName(char *inName);
  210. static int ik_emptyAttachIndex();
  211. static int ik_detachController(int controlIndex);
  212. static int ik_detachInterface(int attachIndex);
  213.  
  214. // timer callback
  215. static void ipk_timeout(void *cookie);
  216. // timer schedule
  217. static void ipk_setTimer();
  218. // send message to controlling socket
  219. void PROJECT_sendMessage(socket_t ctl, ipk_message_t *message);
  220.  
  221. //
  222. // Global structures and data storage
  223. //
  224. // max size of drop Response
  225. #define KFT_dropResponseMax 1000
  226. // drop Connection response
  227. u_int8_t PROJECT_dropResponseBuffer[KFT_dropResponseMax];
  228. int PROJECT_dropResponseLength;
  229. // time of day info
  230. sopt_timeParam_t PROJECT_timeOfDay;
  231. // flags
  232. u_int32_t PROJECT_flags;
  233. // timer Ref Count (firewall enabled)
  234. int32_t PROJECT_timerRefCount;
  235.     // ipk_timeout reschedules itself when PROJECT_timerRefCount>0
  236. int PROJECT_doRateLimit;            // packet matched a rate limit rule
  237.     // index of failover requested 0=none, 1=default, 2=alternate gateway
  238. int PROJECT_failoverRequest;
  239.     // reserve bandwidth info
  240. KFT_reserveInfo_t PROJECT_rReserveInfo;
  241. KFT_reserveInfo_t PROJECT_sReserveInfo;
  242.  
  243.  
  244. //
  245. // Module wide variables (not exported)
  246. //
  247. static int32_t ipk_timerPending;
  248. static int ipk_initted = 0;
  249.  
  250.  
  251. //
  252. // Setup per instance structures and storage
  253. //
  254.  
  255. // maximum number of controllers and DLIL attachments use index values 1..n
  256. // 0 is reserved for "not found"
  257. //#define kMaxControl    8
  258. //#define kMaxAttach 8
  259.  
  260. // Array of controller instances
  261. control_t PROJECT_control[kMaxControl+1];
  262.  
  263. // Global Array of DLIL attach instances
  264. attach_t PROJECT_attach[kMaxAttach+1];
  265.  
  266.  
  267. #pragma mark -- Load and unload kernel extension
  268. //
  269. // Load and unload kernel extension
  270. //
  271. // ---------------------------------------------------------------------------------
  272. //    Ñ IPNetSentry_TNKE_start
  273. // ---------------------------------------------------------------------------------
  274. kern_return_t IPNetSentry_TNKE_start (kmod_info_t * ki, void * data)
  275. {
  276.     int returnValue = KERN_SUCCESS;
  277.     errno_t status;
  278.     lck_grp_attr_t *grp_attributes = 0;
  279.     lck_attr_t *lck_attributes = 0;
  280.     int i;
  281.     
  282.     printf("IPNetSentry_TNKE has loaded!\n");
  283.  
  284.     // set up the tag value associated with this NKE to mark previously seen packets
  285.     status = mbuf_tag_id_find(MY_BUNDLE_ID, &gidtag);
  286.     if (status != 0) {
  287.         printf("IPNetSentry_TNKE_start: mbuf_tag_id_find failed %d\n", status);
  288.         return KERN_FAILURE;
  289.     }
  290.  
  291.     // Allocate a mutex lock
  292.     grp_attributes = lck_grp_attr_alloc_init();
  293.     lck_grp_attr_setdefault(grp_attributes);
  294.     tnke_lock_grp = lck_grp_alloc_init("IPNetSentry_TNKE", grp_attributes);
  295.     lck_grp_attr_free(grp_attributes);
  296.     grp_attributes = 0;
  297.  
  298.     lck_attributes = lck_attr_alloc_init();
  299.     lck_attr_setdefault(lck_attributes);
  300.     lck_attr_setdebug(lck_attributes);
  301.  
  302.     tnke_lock = lck_mtx_alloc_init(tnke_lock_grp, lck_attributes);
  303.  
  304.     lck_attr_free(lck_attributes);
  305.     lck_attributes = 0;
  306.  
  307.     // mutex lock
  308.     lck_mtx_lock(tnke_lock);
  309.     do {
  310.         // already initialized?
  311.         if (ipk_initted) break;
  312.         
  313.         // initialize global storage
  314.         PROJECT_timerRefCount = 0;
  315.         ipk_timerPending = 0;
  316.         PROJECT_timeOfDay.timeStamp = 0;
  317.         PROJECT_flags = 0;
  318.         PROJECT_dropResponseLength = 0;
  319.         
  320.         // initialize our instance storage
  321.         for (i=0; i<=kMaxControl; i++) {
  322.             bzero(&PROJECT_control[i], sizeof(control_t));
  323.         }
  324.         for (i=0; i<=kMaxAttach; i++) {
  325.             bzero(&PROJECT_attach[i], sizeof(attach_t));
  326.         }
  327.         // setup KFT structures
  328.         KFT_init();
  329.                 
  330.         // register our NKE
  331.         status = sflt_register(&ik_sflt_filter, PF_INET,
  332.                       SOCK_DGRAM, IPPROTO_UDP);
  333.  
  334.         if (status != 0) {
  335.             printf("IPNetSentry_TNKE_start: sflt_register failed %d\n", status);
  336.             returnValue = KERN_FAILURE;
  337.         } else {
  338.             registered++;
  339.             ipk_initted = 1;
  340.         }
  341.         
  342.     } while (FALSE);
  343.     // mutex unlock
  344.     lck_mtx_unlock(tnke_lock);
  345.  
  346.     return returnValue;
  347. }
  348.  
  349.  
  350. // ---------------------------------------------------------------------------------
  351. //    Ñ IPNetSentry_TNKE_stop
  352. // ---------------------------------------------------------------------------------
  353. kern_return_t IPNetSentry_TNKE_stop (kmod_info_t * ki, void * data) {
  354.     int returnValue = KERN_SUCCESS;
  355.     errno_t status;
  356.     int i;
  357.  
  358.     // mutex lock
  359.     lck_mtx_lock(tnke_lock);
  360.     do {
  361.         // if not initted
  362.         if (!ipk_initted) break;
  363.         
  364.         // unlink controllers and remove any DLIL attach instances
  365.         for (i=1; i<=kMaxControl; i++) {
  366.             if (PROJECT_control[i].ctl != 0) {
  367.                 ik_detachController(i);
  368.                 // tell any clients the socket has gone away
  369.                 // not sure how to do this, so just fail for now
  370.                 returnValue = KERN_FAILURE;    // fail until all sockets are disconnected
  371.                 break;
  372.             }
  373.         }
  374.         if (returnValue != 0) break;
  375.         
  376.         // remove any remaining attach instances (defensive)
  377.         for (i=1; i<=kMaxAttach; i++) {
  378.             if (PROJECT_attach[i].ifFilterRef || PROJECT_attach[i].ipFilterRef) {
  379.                 ik_detachInterface(i);
  380.             }
  381.         }
  382.         
  383.         // release KFT structures
  384.         KFT_terminate();
  385.         
  386.         // need to cancel any pending kernel callbacks (timeout)
  387.             // fortunately we don't normally unload and can warn the user
  388.             // not to unload while any tools are running
  389.         // force timer ref count to zero
  390.         if (PROJECT_timerRefCount || ipk_timerPending) {
  391.             bsd_untimeout(ipk_timeout, (void *)0);
  392.             PROJECT_timerRefCount = 0;
  393.         }
  394.         
  395.         // unplug our socket filter
  396.         if (unregistered_started == 0) {
  397.             status = sflt_unregister(ik_sflt_filter.sf_handle);
  398.             if (status != 0) {
  399.                 printf("IPNetSentry_TNKE_stop: sflt_unregister failed %d\n", status);
  400.                 returnValue = KERN_FAILURE;
  401.             }
  402.             else {
  403.                 unregistered_started++;
  404.             }
  405.         } else if (unregistered_complete) {
  406.             returnValue = KERN_SUCCESS;
  407.             ipk_initted = 0;
  408.         } else {
  409.             printf("IPNetSentry_TNKE_stop: again\n");
  410.             returnValue = KERN_FAILURE;
  411.         }
  412.     } while (FALSE);
  413.     // mutex unlock
  414.     lck_mtx_unlock(tnke_lock);
  415.     
  416.     // release mutex lock
  417.     if (returnValue == KERN_SUCCESS) {
  418.         if (tnke_lock)
  419.             lck_mtx_free(tnke_lock, tnke_lock_grp);
  420.         if (tnke_lock_grp)
  421.             lck_grp_free(tnke_lock_grp);
  422.         tnke_lock = 0;
  423.         tnke_lock_grp = 0;
  424.     }
  425.     
  426.     if (returnValue == 0) printf("IPNetSentry_TNKE has unloaded!\n");
  427.  
  428.     return returnValue;
  429. }
  430.  
  431. #pragma mark -- Tiger socket intercept functions --
  432.  
  433. static void 
  434. ik_unregistered(sflt_handle handle)
  435. {
  436.     unregistered_complete++;
  437.     return;
  438. }
  439.  
  440. static errno_t    
  441. ik_attach(void **cookie, socket_t so)
  442. {
  443.     //printf("ik_attach: %x\n", so);
  444.     return 0;
  445. }
  446.  
  447. static void    
  448. ik_detach(void *cookie, socket_t so)
  449. {
  450.     //printf("ik_detach: %x\n", so);
  451.     return;
  452. }
  453.  
  454. // this is where we get notified that a socket is closing
  455. static void ik_notify(void *cookie, socket_t so,
  456.                          sflt_event_t event, void *param)
  457. {
  458.     //printf("ik_notify: %x event: %lu\n", so, event);
  459.     if (event == sock_evt_closing) {
  460.         // socket is being closed:
  461.         //     disconnect, turn off monitoring, and detach from interface if no more references.
  462.         // - Any open sockets will be closed by the kernel when the process quits,
  463.         //   so this is our big chance to clean up properly regardless of how the
  464.         //   companion application died.
  465.         ik_disconnect(so);
  466.     }
  467.     return;
  468. }
  469.  
  470. static int
  471. ik_getpeername(void *cookie, socket_t so,
  472.                          struct sockaddr **sa)
  473. {
  474.     return 0;
  475. }
  476.  
  477. static int
  478. ik_getsockname(void *cookie, socket_t so,
  479.                          struct sockaddr **sa)
  480. {
  481.     return 0;
  482. }
  483.  
  484.  
  485. static errno_t    
  486. ik_data_in(void *cookie, socket_t so,
  487.                     const struct sockaddr *from, mbuf_t *data,
  488.                     mbuf_t *control, sflt_data_flag_t flags)
  489. {
  490.     return 0;
  491. }
  492.  
  493. static errno_t
  494. ik_data_out(void *cookie, socket_t so,
  495.                     const struct sockaddr *to, mbuf_t *data,
  496.                     mbuf_t *control, sflt_data_flag_t flags)
  497. {
  498.     return 0;
  499. }
  500.  
  501.  
  502. static errno_t
  503. ik_connect_in(void *cookie, socket_t so,
  504.                     const struct sockaddr *from)
  505. {
  506.     printf("ik_connect_in: %x\n", so);
  507.     return 0;
  508. }
  509.  
  510. static errno_t    
  511. ik_connect_out(void *cookie, socket_t so,
  512.                     const struct sockaddr *to)
  513. {
  514.     printf("ik_connect_in: %x\n", so);
  515.     return 0;
  516. }
  517.  
  518. static errno_t
  519.     ik_bind(void *cookie, socket_t so,
  520.                     const struct sockaddr *to)
  521. {
  522.     return 0;
  523. }
  524.  
  525. // ---------------------------------------------------------------------------------
  526. //    Ñ ik_setoption
  527. // ---------------------------------------------------------------------------------
  528. // intercept socket options (soset and soget)
  529. static errno_t
  530. ik_setoption(void *cookie, socket_t so, sockopt_t sopt)
  531. {
  532.     errno_t returnValue = 0;    // continue normall processing (pass it on)
  533.     errno_t status;
  534.     int controlIndex=0;
  535.     int attachIndex=0;
  536.     int32_t count;
  537.     int valsize, howMany;
  538.  
  539.     do {
  540.         // find our controller instance
  541.         controlIndex = ik_controlIndexForSocket(so);
  542.         if (!controlIndex) {
  543.             // not yet connected, try to connect
  544.             returnValue = ik_connect(so);
  545.             if (returnValue != EJUSTRETURN) break;
  546.             controlIndex = ik_controlIndexForSocket(so);
  547.             if (!controlIndex) {
  548.                 returnValue = ENOTCONN;
  549.                 break;
  550.             }
  551.         }
  552.  
  553.         switch(sockopt_name(sopt)) {
  554.             case SO_ATTACH_LINK:
  555.                 // mutex lock
  556.                 lck_mtx_lock(tnke_lock);
  557.                 do {
  558.                     // attach a controller socket to an IP interface (data link)
  559.                     struct sopt_attachParam attachParam;
  560.                     // Reference: copyin and copyout option parameters
  561.                     //errno_t sockopt_copyin(sockopt_t sopt, void *data, size_t length);
  562.                     //errno_t sockopt_copyout(sockopt_t sopt, void *data, size_t length);
  563.                     #if DEBUG_IPK
  564.                         printf("ik_setoption: received SO_ATTACH_LINK\n");
  565.                     #endif
  566.                     // copyin option parameter
  567.                     returnValue = sockopt_copyin(sopt, &attachParam, sizeof(attachParam));
  568.                     if (returnValue != 0) break;
  569.                     
  570.                     // look for existing DLIL attach by bsdName
  571.                     attachIndex = ik_attachIndexForName(attachParam.bsdName);
  572.                     if (attachIndex) {
  573.                         // found existing DLIL attach
  574.                         // associate this controller with DLIL attach
  575.                         PROJECT_control[controlIndex].attachMap[attachIndex] = 1;
  576.                         returnValue = EJUSTRETURN;
  577.                         break;            
  578.                     }                                    
  579.                     // did not find previous attachment
  580.                     // create a new DLIL attach instance for requested interface
  581.                             // find slot for attach instance
  582.                     attachIndex = ik_emptyAttachIndex();
  583.                     if (!attachIndex) {
  584.                         returnValue = EBUSY;
  585.                         break;
  586.                     }
  587.                     bzero(&PROJECT_attach[attachIndex], sizeof(attach_t));
  588.                     // remember our own index for convenience
  589.                     PROJECT_attach[attachIndex].attachIndex = attachIndex;
  590.                     
  591.                     if (attachParam.protocolFilter) {
  592.                         // Register IPv4 protocol filter
  593.                         struct ipf_filter ipf_filter;
  594.                         ipfilter_t ipFilterRef;
  595.                             // set cookie to point to this attach instance
  596.                         ipf_filter.cookie = (caddr_t)&PROJECT_attach[attachIndex];
  597.                         ipf_filter.name = "com.sustworks.nke.IPNetSentry_TNKE";
  598.                         ipf_filter.ipf_input = (ipf_input_func)ipk_ipf_input_func;
  599.                         ipf_filter.ipf_output = (ipf_output_func)ipk_ipf_output_func;
  600.                         ipf_filter.ipf_detach = (ipf_detach_func)ipk_ipf_detach_func;
  601.                              // attach as IP filter
  602.                         returnValue = ipf_addv4(&ipf_filter, &ipFilterRef);
  603.                         PROJECT_attach[attachIndex].ipFilterRef = ipFilterRef;
  604.                         if (returnValue != 0) {
  605.                             printf("ik_setoption attach: ipf_addv4 failed %d\n", returnValue);
  606.                             break;
  607.                         } else {
  608.                             #if DEBUG_IPK
  609.                             printf("ik_setoption: protocol filter on %s\n", attachParam.bsdName);
  610.                             #endif
  611.                         }
  612.                     }
  613.                     else {
  614.                         // Register as interface filter
  615.                         ifnet_t ifnet_ref = NULL;
  616.                         struct iff_filter iff_filter;
  617.                         interface_filter_t ifFilterRef;
  618.                         // find matching ifnet for interface name (must call ifnet_release)
  619.                         returnValue = ifnet_find_by_name(attachParam.bsdName, &ifnet_ref);
  620.                         if (returnValue != 0) break;
  621.                             // set cookie to point to this attach instance
  622.                         iff_filter.iff_cookie = (caddr_t)&PROJECT_attach[attachIndex];
  623.                         iff_filter.iff_name = "com.sustworks.nke.IPNetSentry_TNKE";
  624.                         //iff_filter.iff_protocol = PF_INET;
  625.                         iff_filter.iff_protocol = 0;    // bridge non PF_INET packets
  626.                         iff_filter.iff_input = ipk_iff_input_func;
  627.                         iff_filter.iff_output = ipk_iff_output_func;
  628.                         iff_filter.iff_event = ipk_iff_event_func;
  629.                         iff_filter.iff_ioctl = ipk_iff_ioctl_func;
  630.                         iff_filter.iff_detached = ipk_iff_detached_func;
  631.                         // attach as interface filter
  632.                         returnValue = iflt_attach(ifnet_ref, &iff_filter, &ifFilterRef);
  633.                         PROJECT_attach[attachIndex].ifFilterRef = ifFilterRef;
  634.                         // remember the ifnet we found (release when detaching)
  635.                         PROJECT_attach[attachIndex].ifnet_ref = ifnet_ref;
  636.                         //if (ifnet_ref) ifnet_release(ifnet_ref);
  637.                         if (returnValue != 0) {
  638.                             printf("ik_setoption attach: iflt_attached failed %d\n", returnValue);
  639.                             break;
  640.                         } else {
  641.                             #if DEBUG_IPK
  642.                             printf("ik_setoption: interface filter on %s\n", attachParam.bsdName);
  643.                             #endif
  644.                         }
  645.                     }
  646.  
  647.                     // remember other attach info
  648.                     {
  649.                         int len;
  650.                         // default to filter on
  651.                         PROJECT_attach[attachIndex].kftInterfaceEntry.filterOn = 1;
  652.                         // remember interface name as CString
  653.                         len = strlen(attachParam.bsdName);
  654.                         memcpy(&PROJECT_attach[attachIndex].kftInterfaceEntry.bsdName[0],
  655.                                         &attachParam.bsdName[0], len+1);
  656.                         // associate this controller with DLIL attach
  657.                         PROJECT_control[controlIndex].attachMap[attachIndex] = 1;
  658.                         #if DEBUG_IPK
  659.                                 printf("ik_setoption control instance: %d attach instance: %d\n",
  660.                                         controlIndex, attachIndex);
  661.                         #endif
  662.                     }
  663.                     // Everything worked, Yay!
  664.                     returnValue = EJUSTRETURN;                    
  665.                 } while (FALSE);
  666.                 // mutex unlock
  667.                 lck_mtx_unlock(tnke_lock);
  668.                 break;
  669.             case SO_DETACH_LINK:
  670.                 // mutex lock
  671.                 lck_mtx_lock(tnke_lock);
  672.                 do {
  673.                     // detach specified interface from controller socket
  674.                     struct sopt_attachParam attachParam;
  675.                     #if DEBUG_IPK
  676.                         printf("ik_setoption: received SO_DETACH_LINK\n");
  677.                     #endif
  678.                     // if name is nil, detach controller and any interface attachments
  679.                     if (sockopt_valsize(sopt) == 0) {
  680.                         #if DEBUG_IPK
  681.                             printf("ik_setoption detach all interfaces\n");
  682.                         #endif
  683.                         returnValue = ik_detachController(controlIndex);
  684.                         if (returnValue != 0) break;
  685.                         returnValue = EJUSTRETURN;
  686.                         break;
  687.                     }
  688.                     // copyin option parameter
  689.                     returnValue = sockopt_copyin(sopt, &attachParam, sizeof(attachParam));
  690.                     if (returnValue != 0) break;
  691.                     // make sure delay table is empty before detaching from any interfaces
  692.                     //KFT_delayAge(0);                
  693.                     // look for existing DLIL attach by bsdName
  694.                     attachIndex = ik_attachIndexForName(attachParam.bsdName);
  695.                     if (attachIndex) {
  696.                         // found existing DLIL attach
  697.                         // dis-associate this controller with attach
  698.                         PROJECT_control[controlIndex].attachMap[attachIndex] = 0;
  699.                         // are there any more references?
  700.                         if (ik_controlCount(attachIndex) == 0) {
  701.                             // no more references to this attach instance
  702.                             ik_detachInterface(attachIndex);
  703.                         }
  704.                     }
  705.                     else {
  706.                         returnValue = ENOENT;
  707.                         break;
  708.                     }
  709.                     returnValue = EJUSTRETURN;
  710.                 } while (FALSE);
  711.                 // mutex unlock
  712.                 lck_mtx_unlock(tnke_lock);
  713.                 break;
  714.             case SO_MONITOR_ON:
  715.                 do {
  716.                     #if DEBUG_IPK
  717.                         printf("ik_setoption: received SO_MONITOR_ON\n");
  718.                     #endif
  719.                     // reset nkeSends to tell NKE we want more
  720.                     PROJECT_control[controlIndex].nkeSends = 0;
  721.                     // check for attachment to an interface
  722.                     if (ik_attachCount(controlIndex) == 0) {
  723.                         returnValue = ENOENT;
  724.                         break;
  725.                     }
  726.                     // if monitoring is not already on
  727.                     if (PROJECT_control[controlIndex].monitorOn == 0) {
  728.                         int32_t result;
  729.                         PROJECT_control[controlIndex].monitorOn = 1;
  730.                         // start 1-second timer to send interface stats upstream
  731.                         //PROJECT_timerRefCount += 1;
  732.                         result = OSAddAtomic(1, (SInt32*)&PROJECT_timerRefCount);
  733.                         result = OSAddAtomic(1, (SInt32*)&ipk_timerPending);
  734.                         if (result == 0) {    // timer is not running
  735.                             #if DEBUG_IPK
  736.                                 printf("ik_setoption: start timer\n");
  737.                             #endif
  738.                             ipk_timeout((void *)0);
  739.                         }
  740.                     }
  741.                     returnValue = EJUSTRETURN;
  742.                 } while (FALSE);
  743.                 break;
  744.             case SO_MONITOR_OFF:
  745.                 do {
  746.                     #if DEBUG_IPK
  747.                         printf("ik_setoption: received SO_MONITOR_OFF\n");
  748.                     #endif
  749.                     PROJECT_control[controlIndex].monitorOn = 0;
  750.                     // bump timer ref count
  751.                     //PROJECT_timerRefCount -= 1;
  752.                     status = OSAddAtomic(-1, (SInt32*)&PROJECT_timerRefCount);
  753.                     if (status <= 0) PROJECT_timerRefCount = 0;    // defensive
  754.                     // report current connection table
  755.                     {
  756.                         // mutex lock
  757.                         lck_mtx_lock(tnke_lock);
  758.                         // do report
  759.                         KFT_connectionReport();
  760.                         // mutex unlock
  761.                         lck_mtx_unlock(tnke_lock);                    
  762.                     }
  763.                     returnValue = EJUSTRETURN;
  764.                 } while (FALSE);
  765.                 break;
  766.             case SO_FILTER_DOWNLOAD:
  767.                 // filter table is downloaded as binary array of table entries
  768.                 // mutex lock
  769.                 lck_mtx_lock(tnke_lock);
  770.                 do {
  771.                     #if DEBUG_IPK
  772.                         printf("ik_setoption: received SO_FILTER_DOWNLOAD\n");
  773.                     #endif
  774.                     // check option length
  775.                     kft_filterTableD.length = sockopt_valsize(sopt);
  776.                     if (kft_filterTableD.length >= kft_filterTableD.bufferLength) {
  777.                         kft_filterTableD.length = kft_filterTableD.bufferLength;
  778.                         #if DEBUG_IPK
  779.                         printf("SO_FILTER_DOWNLOAD buffer space exceeded.\n");
  780.                         #endif
  781.                         returnValue = EMSGSIZE;
  782.                         break;
  783.                     }
  784.                     // copyin option parameter
  785.                     returnValue = sockopt_copyin(sopt, kft_filterTableD.bytes, kft_filterTableD.length);
  786.                     if (returnValue != 0) break;
  787.                     #if DEBUG_IPK
  788.                         printf("ik_setoption: sooptcopyin OK\n");
  789.                     #endif
  790.                     kft_filterTableD.offset = kft_filterTableD.length/sizeof(KFT_filterEntry_t);
  791.                     returnValue = EJUSTRETURN;
  792.                 } while (FALSE);
  793.                 // mutex unlock
  794.                 lck_mtx_unlock(tnke_lock);
  795.                 break;
  796.             case SO_KFT_RESET: {
  797.                 #if DEBUG_IPK
  798.                     printf("ik_setoption: received SO_KFT_RESET\n");
  799.                 #endif
  800.                 // mutex lock
  801.                 lck_mtx_lock(tnke_lock);
  802.                 // reset selected state before downloading
  803.                 KFT_reset();
  804.                 // mutex unlock
  805.                 lck_mtx_unlock(tnke_lock);
  806.                 returnValue = EJUSTRETURN;
  807.                 break;
  808.             }
  809.             case SO_FILTER_UPLOAD: {
  810.                 #if DEBUG_IPK
  811.                     printf("ik_setoption: received SO_FILTER_UPLOAD\n");
  812.                 #endif
  813.                 returnValue = sockopt_copyout(sopt, kft_filterTableD.bytes, kft_filterTableD.length);
  814.                 if (returnValue != 0) break;
  815.                 #if DEBUG_IPK
  816.                     printf("ik_setoption: sooptcopyout OK %d\n",outBuf.length);
  817.                 #endif
  818.                 returnValue = EJUSTRETURN;
  819.                 break;
  820.             }
  821.             case SO_FILTER_COUNT: {
  822.                 #if DEBUG_IPK
  823.                     printf("ik_setoption: received SO_FILTER_COUNT\n");
  824.                 #endif
  825.                 count = KFT_filterCount();
  826.                 returnValue = sockopt_copyout(sopt, &count, sizeof(count));
  827.                 if (returnValue != 0) break;
  828.                 returnValue = EJUSTRETURN;
  829.                 break;
  830.             }
  831.             case SO_TRIGGER_COUNT: {
  832.                 #if DEBUG_IPK
  833.                     printf("ik_setoption: received SO_TRIGGER_COUNT\n");
  834.                 #endif
  835.                 count = KFT_triggerCount();
  836.                 returnValue = sockopt_copyout(sopt, &count, sizeof(count));
  837.                 if (returnValue != 0) break;
  838.                 returnValue = EJUSTRETURN;
  839.                 break;
  840.             }
  841.             case SO_INTERFACE_COUNT: {
  842.                 #if DEBUG_IPK
  843.                     printf("ik_setoption: received SO_INTERFACE_COUNT\n");
  844.                 #endif
  845.                 count = ik_attachCount(controlIndex);
  846.                 returnValue = sockopt_copyout(sopt, &count, sizeof(count));
  847.                 if (returnValue != 0) break;
  848.                 returnValue = EJUSTRETURN;
  849.                 break;
  850.             }
  851. #ifdef IPNetRouter
  852.             case SO_PORTMAP_COUNT: {
  853.                 #if DEBUG_IPK
  854.                     printf("ik_setoption: received SO_PORTMAP_COUNT\n");
  855.                 #endif
  856.                 count = KFT_portMapCount();
  857.                 returnValue = sockopt_copyout(sopt, &count, sizeof(count));
  858.                 if (returnValue != 0) break;
  859.                 returnValue = EJUSTRETURN;
  860.                 break;
  861.             }
  862. #endif
  863.             case SO_SET_TIME: {
  864.                 // set time of day info for NKE
  865.                 #if DEBUG_IPK
  866.                     printf("ik_setoption: received SO_SET_TIME\n");
  867.                 #endif
  868.                 // copyin option parameter
  869.                 returnValue = sockopt_copyin(sopt, &PROJECT_timeOfDay, sizeof(struct sopt_timeParam));
  870.                 if (returnValue != 0) break;
  871.                 returnValue = EJUSTRETURN;
  872.                 break;
  873.             }
  874.             
  875.             case SO_SET_FLAGS: {
  876.                 // set global NKE flags
  877.                 sopt_flagsParam_t flagsParam;
  878.                 // copyin option parameter
  879.                 returnValue = sockopt_copyin(sopt, &flagsParam, sizeof(struct sopt_flagsParam));
  880.                 if (returnValue != 0) break;
  881.                 PROJECT_flags &= ~flagsParam.mask;    // clear bits we're going to modify
  882.                 PROJECT_flags |= flagsParam.flags;    // set bits to effect change
  883.                 returnValue = EJUSTRETURN;
  884.                 #if DEBUG_IPK
  885.                     KFT_logText("ik_setoption: received SO_SET_FLAGS ", &PROJECT_flags);
  886.                 #endif
  887.                 break;
  888.             }
  889.             case SO_GET_FLAGS: {
  890.                 // get global NKE flags
  891.                 sopt_flagsParam_t flagsParam;
  892.                 flagsParam.flags = PROJECT_flags;
  893.                 flagsParam.mask = 0xFFFFFFFF;
  894.                 // return current value
  895.                 returnValue = sockopt_copyout(sopt, &flagsParam, sizeof(flagsParam));
  896.                 if (returnValue != 0) break;
  897.                 returnValue = EJUSTRETURN;
  898.                 break;
  899.             }
  900.             
  901.             case SO_DROP_RESPONSE: {
  902.                 #if DEBUG_IPK
  903.                     printf("ik_setoption: received SO_DROP_RESPONSE\n");
  904.                 #endif
  905.                 // check length of option parameter
  906.                 PROJECT_dropResponseLength = sockopt_valsize(sopt);
  907.                 if (PROJECT_dropResponseLength < KFT_dropResponseMax-60) {
  908.                     // copyin option parameter
  909.                     // leave room for link header, ip header, tcp header
  910.                     returnValue = sockopt_copyin(sopt, &PROJECT_dropResponseBuffer[60], PROJECT_dropResponseLength);
  911.                     if (returnValue != 0) break;
  912.                 }
  913.                 else {
  914.                     returnValue = E2BIG;
  915.                     break;
  916.                 }
  917.                 #if DEBUG_IPK
  918.                     printf("ik_setoption: sooptcopyin OK %d\n",PROJECT_dropResponseLength);
  919.                 #endif
  920.                 returnValue = EJUSTRETURN;
  921.                 break;
  922.             }
  923.             case SO_TRIGGER_DURATION: {
  924.                 #if DEBUG_IPK
  925.                     printf("ik_setoption: received SO_TRIGGER_EXPIRATION\n");
  926.                 #endif
  927.                 // copyin option parameter
  928.                 returnValue = sockopt_copyin(sopt, &count, sizeof(count));
  929.                 if (returnValue != 0) break;
  930.                 count = KFT_triggerDuration(count);
  931.                 // return current value
  932.                 returnValue = sockopt_copyout(sopt, &count, sizeof(count));
  933.                 if (returnValue != 0) break;
  934.                 returnValue = EJUSTRETURN;
  935.                 break;
  936.             }        
  937.             case SO_TRIGGER_ADDRESS: {
  938.                 KFT_triggerKey_t value[101];
  939.                 #if DEBUG_IPK
  940.                     printf("ik_setoption: received SO_TRIGGER_ADDRESS\n");
  941.                 #endif
  942.                 // check parameter size
  943.                 valsize = sockopt_valsize(sopt);
  944.                 if (valsize <= sizeof(KFT_triggerKey_t)*100) {
  945.                     // copyin option parameter
  946.                     returnValue = sockopt_copyin(sopt, value, valsize);
  947.                     if (returnValue != 0) break;
  948.                 }
  949.                 else {
  950.                     returnValue = E2BIG;
  951.                     break;
  952.                 }
  953.                 howMany = valsize/sizeof(KFT_triggerKey_t);
  954.                 // mutex lock
  955.                     lck_mtx_lock(tnke_lock);                
  956.                 KFT_triggerRemoveByKey(value, howMany);
  957.                 // mutex unlock
  958.                     lck_mtx_unlock(tnke_lock);                
  959.                 // are there any more updates to send?
  960.                 KFT_triggerSendUpdates();
  961.                 returnValue = EJUSTRETURN;
  962.                 break;
  963.             }
  964.             case SO_TRIGGER_UPLOAD: {
  965.                 #if DEBUG_IPK
  966.                     printf("ik_setoption: received SO_TRIGGER_UPLOAD\n");
  967.                 #endif
  968.                 // mutex lock
  969.                 lck_mtx_lock(tnke_lock);
  970.                 
  971.                 count = KFT_triggerUpload();
  972.                 sockopt_copyout(sopt, &count, sizeof(count));
  973.  
  974.                 // mutex unlock
  975.                 lck_mtx_unlock(tnke_lock);
  976.                 returnValue = EJUSTRETURN;
  977.                 break;
  978.             }
  979.             case SO_INTERFACE_UPLOAD: {
  980.                 #if DEBUG_IPK
  981.                     printf("ik_setoption: received SO_INTERFACE_UPLOAD\n");
  982.                 #endif
  983.                 // mutex lock
  984.                 lck_mtx_lock(tnke_lock);
  985.                 
  986.                 count = KFT_interfaceUpload();
  987.                 sockopt_copyout(sopt, &count, sizeof(count));
  988.  
  989.                 // mutex unlock
  990.                 lck_mtx_unlock(tnke_lock);
  991.                 returnValue = EJUSTRETURN;
  992.                 break;
  993.             }
  994. #ifdef IPNetRouter
  995.             case SO_PORTMAP_UPLOAD: {
  996.                 #if DEBUG_IPK
  997.                     printf("ik_setoption: received SO_PORTMAP_UPLOAD\n");
  998.                 #endif
  999.                 // mutex lock
  1000.                 lck_mtx_lock(tnke_lock);
  1001.                 
  1002.                 count = KFT_portMapUpload();
  1003.                 sockopt_copyout(sopt, &count, sizeof(count));
  1004.  
  1005.                 // mutex unlock
  1006.                 lck_mtx_unlock(tnke_lock);
  1007.                 returnValue = EJUSTRETURN;
  1008.                 break;
  1009.             }
  1010.             case SO_NAT_UPLOAD: {
  1011.                 #if DEBUG_IPK
  1012.                     printf("ik_setoption: received SO_NAT_UPLOAD\n");
  1013.                 #endif
  1014.                 // mutex lock
  1015.                 lck_mtx_lock(tnke_lock);
  1016.                 
  1017.                 count = KFT_natUpload();
  1018.                 sockopt_copyout(sopt, &count, sizeof(count));
  1019.  
  1020.                 // mutex unlock
  1021.                 lck_mtx_unlock(tnke_lock);
  1022.                 returnValue = EJUSTRETURN;
  1023.                 break;
  1024.             }
  1025. #endif
  1026.             case SO_IPK_MESSAGE: {
  1027.                 // accept ipk_message as downstream data
  1028.                 unsigned char buffer[kUpdateBufferSize];
  1029.                 ipk_message_t* message;
  1030.                 message = (ipk_message_t*)&buffer[0];
  1031.                 #if DEBUG_IPK
  1032.                     printf("ik_setoption: received SO_IPK_MESSAGE\n");
  1033.                 #endif
  1034.                 // check parameter size
  1035.                 valsize = sockopt_valsize(sopt);
  1036.                 if (valsize <= kUpdateBufferSize) {
  1037.                     // copyin option parameter
  1038.                     returnValue = sockopt_copyin(sopt, &buffer[0], valsize);
  1039.                     if (returnValue != 0) break;
  1040.                 }
  1041.                 else {
  1042.                     returnValue = E2BIG;
  1043.                     break;
  1044.                 }
  1045.                 if (valsize < sizeof(ipk_message_t)) break;
  1046.                 // pass along to KFT for processing
  1047.                 KFT_receiveMessage(message);
  1048.                 returnValue = EJUSTRETURN;
  1049.                 break;
  1050.             }
  1051.             default: {
  1052.                 #if DEBUG_IPK
  1053.                     printf("ik_setoption: default unrecognized sopt->sopt_name=%x pass it on\n", sockopt_name(sopt));
  1054.                 #endif
  1055.                 returnValue = 0;
  1056.                 break;
  1057.             }
  1058.         }    // end switch
  1059.     } while (FALSE);
  1060.     #if 0
  1061.         printf("ik_setoption returnValue: %d\n", returnValue);
  1062.     #endif    
  1063.     return returnValue;
  1064. }
  1065.                     
  1066. static errno_t
  1067. ik_getoption(void *cookie, socket_t so, sockopt_t sopt)
  1068. {
  1069.     errno_t returnValue = 0;    // continue normall processing (pass it on)
  1070.     //errno_t status;
  1071.     int controlIndex=0;
  1072.     //int attachIndex=0;
  1073.     int32_t count;
  1074.  
  1075.     do {
  1076.         // find our controller instance
  1077.         controlIndex = ik_controlIndexForSocket(so);
  1078.         if (!controlIndex) {
  1079.             // not yet connected, try to connect
  1080.             returnValue = ik_connect(so);
  1081.             if (returnValue != EJUSTRETURN) break;
  1082.             controlIndex = ik_controlIndexForSocket(so);
  1083.             if (!controlIndex) {
  1084.                 returnValue = ENOTCONN;
  1085.                 break;
  1086.             }
  1087.         }
  1088.  
  1089.         switch(sockopt_name(sopt)) {
  1090.             case SO_FILTER_UPLOAD: {
  1091.                 #if DEBUG_IPK
  1092.                     printf("ik_setoption: received SO_FILTER_UPLOAD\n");
  1093.                 #endif
  1094.                 returnValue = sockopt_copyout(sopt, kft_filterTableD.bytes, kft_filterTableD.length);
  1095.                 if (returnValue != 0) break;
  1096.                 #if DEBUG_IPK
  1097.                     printf("ik_setoption: sooptcopyout OK %d\n",outBuf.length);
  1098.                 #endif
  1099.                 returnValue = EJUSTRETURN;
  1100.                 break;
  1101.             }
  1102.             case SO_FILTER_COUNT: {
  1103.                 #if DEBUG_IPK
  1104.                     printf("ik_setoption: received SO_FILTER_COUNT\n");
  1105.                 #endif
  1106.                 count = KFT_filterCount();
  1107.                 returnValue = sockopt_copyout(sopt, &count, sizeof(count));
  1108.                 if (returnValue != 0) break;
  1109.                 returnValue = EJUSTRETURN;
  1110.                 break;
  1111.             }
  1112.             case SO_TRIGGER_COUNT: {
  1113.                 #if DEBUG_IPK
  1114.                     printf("ik_setoption: received SO_TRIGGER_COUNT\n");
  1115.                 #endif
  1116.                 count = KFT_triggerCount();
  1117.                 returnValue = sockopt_copyout(sopt, &count, sizeof(count));
  1118.                 if (returnValue != 0) break;
  1119.                 returnValue = EJUSTRETURN;
  1120.                 break;
  1121.             }
  1122.             case SO_INTERFACE_COUNT: {
  1123.                 #if DEBUG_IPK
  1124.                     printf("ik_setoption: received SO_INTERFACE_COUNT\n");
  1125.                 #endif
  1126.                 count = ik_attachCount(controlIndex);
  1127.                 returnValue = sockopt_copyout(sopt, &count, sizeof(count));
  1128.                 if (returnValue != 0) break;
  1129.                 returnValue = EJUSTRETURN;
  1130.                 break;
  1131.             }
  1132. #ifdef IPNetRouter
  1133.             case SO_PORTMAP_COUNT: {
  1134.                 #if DEBUG_IPK
  1135.                     printf("ik_setoption: received SO_PORTMAP_COUNT\n");
  1136.                 #endif
  1137.                 count = KFT_portMapCount();
  1138.                 returnValue = sockopt_copyout(sopt, &count, sizeof(count));
  1139.                 if (returnValue != 0) break;
  1140.                 returnValue = EJUSTRETURN;
  1141.                 break;
  1142.             }
  1143. #endif
  1144.             default: {
  1145.                 #if DEBUG_IPK
  1146.                     printf("ik_getoption: default unrecognized sopt->sopt_name=%x pass it on\n", sockopt_name(sopt));
  1147.                 #endif
  1148.                 returnValue = 0;
  1149.                 break;
  1150.             }
  1151.         }    // end switch
  1152.     } while (FALSE);
  1153.     #if 0
  1154.         printf("ik_getoption returnValue: %d\n", returnValue);
  1155.     #endif    
  1156.     return returnValue;
  1157. }
  1158.  
  1159.  
  1160. static    errno_t
  1161. ik_listen(void *cookie, socket_t so)
  1162. {
  1163.     return 0;
  1164. }
  1165.                  
  1166.  
  1167. static    errno_t
  1168. ik_ioctl(void *cookie, socket_t so,
  1169.                     u_int32_t request, const char* argp)
  1170. {
  1171.     return 0;
  1172. }
  1173.  
  1174.  
  1175. #pragma mark -- Tiger protocol filter intercept functions
  1176. // ---------------------------------------------------------------------------------
  1177. //    Ñ ipk_ipf_input_func
  1178. // ---------------------------------------------------------------------------------
  1179. // Notice we are called to filter IP packets so we assume the mbuf contains a PKTHDR
  1180. static errno_t 
  1181. ipk_ipf_input_func(caddr_t cookie, mbuf_t *data, int hlen, u_int8_t protocol)
  1182. {
  1183.     int returnValue = 0;
  1184.     attach_t* myAttach;
  1185.     size_t len;
  1186.  
  1187.     // avoid duplicates
  1188.     if ( PROJECT_is_mtag(*data, TAG_IN) ) return 0;
  1189.     returnValue = PROJECT_mtag(*data, TAG_IN);
  1190.     if (returnValue != 0) return returnValue;    // if allocation failed, get out
  1191.     
  1192.     // get access to our attach instance
  1193.     myAttach = (attach_t*)cookie;
  1194.     
  1195.     // IPNetRouterX does not use protocol filter NKEs at this time
  1196. #if 0
  1197.     KFT_packetData_t packet;
  1198.     bzero(&packet, sizeof(packet));
  1199.     packet.ipOffset = 0;
  1200.     packet.direction = 1;
  1201.     packet.myAttach = myAttach;
  1202.     returnValue = KFT_filterPacket(&packet);
  1203. #endif
  1204.     
  1205.     // count receive traffic
  1206.     len = mbuf_pkthdr_len(*data);
  1207.     OSAddAtomic(len, (SInt32*)&myAttach->receiveCount);
  1208.     
  1209.     return returnValue;
  1210. }
  1211.  
  1212. static errno_t 
  1213. ipk_ipf_output_func(caddr_t cookie, mbuf_t *data, ipf_pktopts_t options)
  1214. {
  1215.     int returnValue = 0;
  1216.     attach_t* myAttach;
  1217.     size_t len;
  1218.  
  1219.     // avoid duplicates
  1220.     if ( PROJECT_is_mtag(*data, TAG_OUT) ) return 0;
  1221.     returnValue = PROJECT_mtag(*data, TAG_OUT);
  1222.     if (returnValue != 0) return returnValue;    // if allocation failed, get out
  1223.  
  1224.     // get access to our attach instance
  1225.     myAttach = (attach_t*)cookie;
  1226.     
  1227.     // Count whatever we get at this level.  Notice VPN might be counted twice.
  1228.     //if (protocol != IPPROTO_ICMP && protocol != IPPROTO_TCP &&  protocol != IPPROTO_TCP) return 0;
  1229.     
  1230.     // Notice we are called to filter IP packets so we assume the mbuf contains a PKTHDR
  1231.     //mbuf_flags_t flags = mbuf_flags(*data);
  1232.     //if (flags & MBUF_PKTHDR)
  1233.     
  1234.     // IPNetSentryX does not use protocol filter NKEs at this time
  1235. #if 0
  1236.     KFT_packetData_t packet;
  1237.     bzero(&packet, sizeof(packet));
  1238.     packet.ipOffset = 0;
  1239.     packet.direction = 0;
  1240.     packet.myAttach = myAttach;
  1241.     returnValue = KFT_filterPacket(&packet);
  1242. #endif
  1243.     // count receive traffic
  1244.     len = mbuf_pkthdr_len(*data);
  1245.     //myAttach->sendCount += len;
  1246.     OSAddAtomic(len, (SInt32*)&myAttach->sendCount);
  1247.     
  1248.     return returnValue;
  1249. }
  1250.  
  1251. static void 
  1252. ipk_ipf_detach_func(caddr_t cookie)
  1253. {
  1254.     //printf("ipk_ipf_detach_func: %x\n", *(ipfilter_t*)cookie);
  1255. }
  1256.  
  1257.  
  1258. #pragma mark -- Tiger interface filter intercept functions
  1259.  
  1260. static void ipk_iff_detached_func(
  1261.     void *cookie, 
  1262.     ifnet_t interface)
  1263. {
  1264.  
  1265. static void ipk_iff_event_func(
  1266.     void *cookie, 
  1267.     ifnet_t interface, 
  1268.     protocol_family_t protocol, 
  1269.     const struct kev_msg *event_msg)
  1270. {
  1271.     // check for interface detaching event
  1272.     if (event_msg->event_code == KEV_DL_IF_DETACHING) {
  1273.         attach_t* myAttach;
  1274.         u_int8_t attachIndex;
  1275.         // get access to our attach instance
  1276.         myAttach = (attach_t*)cookie;
  1277.         attachIndex = myAttach->attachIndex;
  1278.         // make sure interface is detached
  1279.         if (PROJECT_attach[attachIndex].ifnet_ref) {
  1280.             PROJECT_lock();
  1281.             ik_detachInterface(attachIndex);
  1282.             PROJECT_unlock();
  1283.         }
  1284.     }
  1285. }
  1286.  
  1287. static errno_t ipk_iff_input_func(
  1288.     void *cookie, 
  1289.     ifnet_t interface, 
  1290.     protocol_family_t protocol, 
  1291.     mbuf_t *data, 
  1292.     char **frame_ptr)
  1293. {
  1294.     int returnValue = 0;
  1295.     attach_t* myAttach;
  1296.     int32_t len;
  1297.  
  1298.     // avoid duplicates
  1299.     if ( PROJECT_is_mtag(*data, TAG_IN) ) return 0;
  1300.     returnValue = PROJECT_mtag(*data, TAG_IN);
  1301.     if (returnValue != 0) return returnValue;    // if allocation failed, get out
  1302.  
  1303.      // get access to our attach instance
  1304.     myAttach = (attach_t*)cookie;
  1305.         
  1306.     // Notice we are called to filter IP packets so we assume the mbuf_t contains a PKTHDR
  1307.     //mbuf_flags_t flags = mbuf_flags(*data);
  1308.     //if (flags & MBUF_PKTHDR)
  1309.     
  1310.     // count receive traffic
  1311.     len = mbuf_pkthdr_len(*data);
  1312. //    myAttach->receiveCount += len;
  1313.     OSAddAtomic(len, (SInt32*)&myAttach->receiveCount);
  1314.  
  1315.     // IP filtering
  1316.     if (PROJECT_timerRefCount) {
  1317.         // mutex lock
  1318.         lck_mtx_lock(tnke_lock);
  1319.         
  1320.         KFT_packetData_t packet;
  1321.         bzero(&packet, sizeof(packet));
  1322.         // passed in
  1323.         packet.ifnet_ref = interface;
  1324.         packet.protocol = protocol;
  1325.         packet.mbuf_ptr = data;
  1326.         packet.frame_ptr = frame_ptr;
  1327.         packet.myAttach = myAttach;        // cookie
  1328.         // link layer info
  1329.         packet.ifType = ifnet_type(interface);
  1330.         packet.ifHeaderLen = ifnet_hdrlen(interface);
  1331.         // check frame header for IPv4
  1332.         if (packet.ifType == IFT_ETHER) {
  1333.             u_int16_t* dp16;
  1334.             if (*frame_ptr) {    // defensive
  1335.                 dp16 = (u_int16_t*)(*frame_ptr);
  1336.                 if (dp16[6] != 0x0800) packet.bridgeNonIP = 1;
  1337.             }
  1338.         }
  1339.         // packet  info
  1340.         packet.ipOffset = 0;
  1341.         packet.direction = 1;
  1342.         // pass to filter
  1343.         returnValue = KFT_filterPacket(&packet);
  1344.  
  1345.         // mutex unlock
  1346.         lck_mtx_unlock(tnke_lock);
  1347.     }
  1348.     
  1349.     return returnValue;
  1350. }
  1351.  
  1352. static errno_t ipk_iff_ioctl_func(
  1353.     void *cookie,
  1354.     ifnet_t interface,
  1355.     protocol_family_t protocol, 
  1356.     u_long ioctl_cmd,
  1357.     void* ioctl_arg)
  1358. {
  1359.     return EOPNOTSUPP;
  1360. }
  1361.  
  1362. static errno_t ipk_iff_output_func(
  1363.     void *cookie,
  1364.     ifnet_t interface,
  1365.     protocol_family_t protocol, 
  1366.     mbuf_t *data)
  1367. {
  1368.     int returnValue = 0;
  1369.     attach_t* myAttach;
  1370.     int32_t len;
  1371.  
  1372.     // avoid duplicates
  1373.     if ( PROJECT_is_mtag(*data, TAG_OUT) ) return 0;
  1374.     returnValue = PROJECT_mtag(*data, TAG_OUT);
  1375.     if (returnValue != 0) return returnValue;    // if allocation failed, get out
  1376.  
  1377.     // get access to our attach instance
  1378.     myAttach = (attach_t*)cookie;
  1379.     
  1380.     // Count whatever we get at this level.  Notice VPN might be counted twice.
  1381.     //if (protocol != IPPROTO_ICMP && protocol != IPPROTO_TCP &&  protocol != IPPROTO_TCP) return 0;
  1382.     
  1383.     // Notice we are called to filter IP packets so we assume the mbuf_t contains a PKTHDR
  1384.     //mbuf_flags_t flags = mbuf_flags(*data);
  1385.     //if (flags & MBUF_PKTHDR)
  1386.     
  1387.     // count receive traffic
  1388.     len = mbuf_pkthdr_len(*data) - ifnet_hdrlen(interface);
  1389. //    myAttach->sendCount += len;
  1390.     OSAddAtomic(len, (SInt32*)&myAttach->sendCount);
  1391.  
  1392.     // IP filtering
  1393.     if (PROJECT_timerRefCount) {
  1394.         // mutex lock
  1395.         lck_mtx_lock(tnke_lock);
  1396.         
  1397.         KFT_packetData_t packet;
  1398.         bzero(&packet, sizeof(packet));
  1399.         // passed in
  1400.         packet.ifnet_ref = interface;
  1401.         packet.protocol = protocol;
  1402.         packet.mbuf_ptr = data;
  1403.         packet.frame_ptr = 0;
  1404.         packet.myAttach = myAttach;
  1405.         // link layer info
  1406.         packet.ifType = ifnet_type(interface);
  1407.         packet.ifHeaderLen = ifnet_hdrlen(interface);
  1408.  
  1409.         // fix header to work around PPP bug
  1410.         if (packet.ifType == IFT_PPP) {
  1411.             // fix header to work around PPP bug
  1412.             //if ((m->m_data[headerLength-2] & 0xF0) == 0x40) headerLength -= 2;
  1413.             u_int8_t* dp = mbuf_data(*data);
  1414.             if ((dp[packet.ifHeaderLen-2] & 0xF0) == 0x40) packet.ifHeaderLen -= 2;
  1415.         }
  1416.         
  1417.         // check frame header for IP
  1418.         if (packet.ifType == IFT_ETHER) {
  1419.             u_int16_t* dp16;
  1420.             dp16 = (u_int16_t*)mbuf_data(*data);
  1421.             if (dp16[6] != 0x0800) packet.bridgeNonIP = 1;
  1422.         }
  1423.         // packet info
  1424.         packet.ipOffset = packet.ifHeaderLen;        // output packets preceeded by frame header
  1425.         packet.direction = 0;
  1426.         // pass to filter
  1427.         returnValue = KFT_filterPacket(&packet);
  1428.  
  1429.         // mutex unlock
  1430.         lck_mtx_unlock(tnke_lock);
  1431.     }
  1432.     
  1433.     return returnValue;
  1434. }
  1435.  
  1436.  
  1437. #pragma mark -- NKE support functions --
  1438. #pragma mark does mutex lock
  1439.  
  1440. // ---------------------------------------------------------------------------------
  1441. //    Ñ PROJECT_lock
  1442. // ---------------------------------------------------------------------------------
  1443. void PROJECT_lock()
  1444. {
  1445.     // lock to allow one thread at a time
  1446.     lck_mtx_lock(tnke_lock);
  1447. }
  1448. // ---------------------------------------------------------------------------------
  1449. //    Ñ PROJECT_unlock
  1450. // ---------------------------------------------------------------------------------
  1451. void PROJECT_unlock()
  1452. {
  1453.     // unlock
  1454.     lck_mtx_unlock(tnke_lock);
  1455. }
  1456.  
  1457. // ---------------------------------------------------------------------------------
  1458. //    Ñ ik_connect
  1459. // ---------------------------------------------------------------------------------
  1460. //    Register connection between controller socket and our NKE
  1461. //    Called via PF_NKE, ik_setoption (set_SO) and also soconnect (standard UDP)
  1462. static int ik_connect(socket_t cso)
  1463. {
  1464.     int returnValue = 0;
  1465.     int controlIndex;
  1466. #if DEBUG_IPK
  1467.             printf("ik_connect\n");
  1468. #endif
  1469.     // mutex lock
  1470.     lck_mtx_lock(tnke_lock);
  1471.  
  1472.     do {
  1473.         // check if this controller socket is already connected
  1474.         controlIndex = ik_controlIndexForSocket(cso);
  1475.         if (controlIndex) {    // found it
  1476.             returnValue = EISCONN;
  1477.             break;
  1478.         }
  1479.  
  1480.         // find slot for connection instance
  1481.         controlIndex = ik_emptyControlIndex();
  1482.         if (!controlIndex) {
  1483.             returnValue = EBUSY;
  1484.             break;        // all connection slots full
  1485.         }
  1486.         // register we have a connection
  1487.         PROJECT_control[controlIndex].ctl = cso;
  1488.         // we don't retain the socket since we want to be notified when it closes.
  1489.         returnValue = EJUSTRETURN;
  1490.     } while (FALSE);
  1491.  
  1492.     // mutex unlock
  1493.     lck_mtx_unlock(tnke_lock);
  1494.     
  1495.     return returnValue;
  1496. }
  1497.  
  1498.  
  1499. // ---------------------------------------------------------------------------------
  1500. //    Ñ ik_disconnect
  1501. // ---------------------------------------------------------------------------------
  1502. static void ik_disconnect(socket_t cso)
  1503. {
  1504.     int controlIndex;
  1505.  
  1506.     #if DEBUG_IPK
  1507.         printf("ik_disconnect\n");
  1508.     #endif
  1509.     // mutex lock
  1510.     lck_mtx_lock(tnke_lock);
  1511.     
  1512.     // check if this controller socket is connected and remove it
  1513.     controlIndex = ik_controlIndexForSocket(cso);
  1514.     if (controlIndex) {    // found it
  1515.         // remove reference to attach instance and clear control instance
  1516.         ik_detachController(controlIndex);
  1517.     }
  1518.     
  1519.     // mutex unlock
  1520.     lck_mtx_unlock(tnke_lock);
  1521. }
  1522.  
  1523. // ---------------------------------------------------------------------------------
  1524. //    Ñ ipk_timeout
  1525. // ---------------------------------------------------------------------------------
  1526. //    one second timer used for monitoring
  1527. //    reschedules itself to be called each second when timerRefCount > 0
  1528. static void ipk_timeout(void *cookie)
  1529. {
  1530.     // lock to allow one thread at a time
  1531.     lck_mtx_lock(tnke_lock);
  1532.  
  1533.     KFT_filterPeriodical();
  1534.     ipk_setTimer();
  1535.     // unlock
  1536.     lck_mtx_unlock(tnke_lock);
  1537. }
  1538.  
  1539. #pragma mark no mutex lock (caller must have it)
  1540.  
  1541. // ---------------------------------------------------------------------------------
  1542. //    Ñ ipk_setTimer
  1543. // ---------------------------------------------------------------------------------
  1544. //    reschedules timer to be called each second when timerRefCount > 0
  1545. static void ipk_setTimer()
  1546. {
  1547.     struct timespec ts;    
  1548.     ts.tv_sec = 1;        // one second interval
  1549.     ts.tv_nsec = 0;
  1550.     // reschedule ourself if anyone needs us
  1551.         // timeout(void (*func)(), void *cookie, int ticks);
  1552.     if (PROJECT_timerRefCount > 0) {
  1553.         ipk_timerPending = TRUE;
  1554.         bsd_timeout(ipk_timeout, (void *)0, &ts);
  1555.     }
  1556.     else {
  1557.         ipk_timerPending = FALSE;
  1558.         #if DEBUG_IPK
  1559.             printf("ipk_timeout: stop timer\n");
  1560.         #endif
  1561.     }    
  1562. }
  1563.  
  1564. // ---------------------------------------------------------------------------------
  1565. //    Ñ PROJECT_sendMessageToAll
  1566. // ---------------------------------------------------------------------------------
  1567. //     send message to each active controller
  1568. void PROJECT_sendMessageToAll(ipk_message_t *message)
  1569. {
  1570.     int i;
  1571.     for (i=1;i<=kMaxControl;i++) {
  1572.         if (PROJECT_control[i].ctl) {
  1573.             // increment NKE sends since last request so we don't
  1574.             // keep flooding input queue when no one is listening.
  1575.             PROJECT_control[i].nkeSends += 1;
  1576.             if (PROJECT_control[i].nkeSends < 250) {        // max messages allowed in 2.5 seconds
  1577.                 PROJECT_sendMessage(PROJECT_control[i].ctl, message);
  1578.             }
  1579.         }
  1580.     }
  1581. }
  1582.  
  1583. // ---------------------------------------------------------------------------------
  1584. //    Ñ PROJECT_sendMessage
  1585. // ---------------------------------------------------------------------------------
  1586. //     send message to controlling socket
  1587. //  assumes caller has mutex lock
  1588. void PROJECT_sendMessage(socket_t ctl, ipk_message_t *message)
  1589. {
  1590.     struct sockaddr from;
  1591.     mbuf_t mbuf;
  1592.     errno_t status;
  1593.     
  1594.     do {
  1595.         void* dp;            // pointer to actual mbuf data
  1596.         size_t size;
  1597.         if (!ctl) break;    // defensive
  1598.         
  1599.         // setup from address
  1600.         bzero(&from, 16);
  1601.         from.sa_len = 16;
  1602.         from.sa_family = PF_INET;
  1603.         
  1604.         // get mbuf with cluster to hold our message
  1605.         status = mbuf_getpacket(MBUF_DONTWAIT, &mbuf);
  1606.         if (status != 0) break;
  1607.         
  1608.         status = mbuf_settype(mbuf, MBUF_TYPE_DATA);
  1609.         
  1610.         // confirm we have enough space for message
  1611.         size = mbuf_maxlen(mbuf);
  1612.         if (message->length > size) {
  1613.             mbuf_freem(mbuf);
  1614.             printf("sendMessage: mbuf too small for message\n");
  1615.             break;
  1616.         }
  1617.         // copy data to cluster
  1618.         dp = mbuf_datastart(mbuf);
  1619.         bcopy(message, dp, message->length);
  1620.         // set data and length
  1621.         status = mbuf_setdata(mbuf, dp, message->length);
  1622.         if (status != 0) {
  1623.             mbuf_freem(mbuf);
  1624.             printf("mbuf_setData: failed %d\n",status);
  1625.             break;
  1626.         }
  1627.         
  1628.         // inject data to socket
  1629.         status = sock_inject_data_in(
  1630.             ctl,
  1631.             &from, 
  1632.             mbuf,
  1633.             NULL,
  1634.             sock_data_filt_flag_record);
  1635.             
  1636.         if (status != 0) {
  1637.             mbuf_freem(mbuf);
  1638.             printf("sock_inject_data_in: failed %d\n",status);
  1639.             break;
  1640.         }
  1641.  
  1642.     } while (FALSE);
  1643. }
  1644.  
  1645. // ---------------------------------------------------------------------------------
  1646. //    Ñ ik_attachCount
  1647. // ---------------------------------------------------------------------------------
  1648. // how many attachments does this controller reference
  1649. static int ik_attachCount(int controlIndex)
  1650. {
  1651.     int count, i;
  1652.     count = 0;
  1653.     // valid controlIndex?
  1654.     if ((controlIndex > 0) && (controlIndex <= kMaxControl)) {
  1655.         // for each attach instance
  1656.         for (i=1; i<=kMaxAttach; i++) {
  1657.             // does this controller reference it
  1658.             if (PROJECT_control[controlIndex].attachMap[i]) count += 1;
  1659.         }
  1660.     }
  1661.     return count;    
  1662. }
  1663.  
  1664. // ---------------------------------------------------------------------------------
  1665. //    Ñ ik_controlCount
  1666. // ---------------------------------------------------------------------------------
  1667. // how many controllers reference this attachment
  1668. static int ik_controlCount(int attachIndex)
  1669. {
  1670.     int count, i;
  1671.     count = 0;
  1672.     // valid attachIndex?
  1673.     if ((attachIndex > 0) && (attachIndex <= kMaxAttach)) {
  1674.         // for each control instance
  1675.         for (i=1; i<=kMaxControl; i++) {
  1676.             // does it reference this attach instance
  1677.             if (PROJECT_control[i].attachMap[attachIndex]) count += 1;
  1678.         }
  1679.     }
  1680.     return count;
  1681. }
  1682.  
  1683. // ---------------------------------------------------------------------------------
  1684. //    Ñ ik_controlIndexForSocket
  1685. // ---------------------------------------------------------------------------------
  1686. //    Find controller instance with corresponding socket if any and pass back it's index.
  1687. //    Returns 0 for not found
  1688. static int ik_controlIndexForSocket(socket_t so)
  1689. {
  1690.     int returnValue = 0;        // controller not connected ENOTCONN
  1691.     int i;
  1692.     
  1693.     for (i=1; i<=kMaxControl; i++) {
  1694.         if (PROJECT_control[i].ctl == so) {
  1695.             returnValue = i;
  1696.             break;
  1697.         }
  1698.     }
  1699.     return returnValue;
  1700. }
  1701.  
  1702.  
  1703. // ---------------------------------------------------------------------------------
  1704. //    Ñ ik_emptyControlIndex
  1705. // ---------------------------------------------------------------------------------
  1706. //    Find an empty controller instance (available slot)
  1707. //    Returns 0 for not found
  1708. static int ik_emptyControlIndex()
  1709. {
  1710.     int returnValue = 0;        // all slots in use EBUSY
  1711.     int i;
  1712.     
  1713.     for (i=1; i<=kMaxControl; i++) {
  1714.         if (PROJECT_control[i].ctl == 0) {
  1715.             returnValue = i;
  1716.             break;
  1717.         }
  1718.     }
  1719.     return returnValue;
  1720. }
  1721.  
  1722. // ---------------------------------------------------------------------------------
  1723. //    Ñ ik_attachIndexForName
  1724. // ---------------------------------------------------------------------------------
  1725. //    Find attach instance with corresponding bsdName.
  1726. //    Return 0 for not found.
  1727. static int ik_attachIndexForName(char *inName)
  1728. {
  1729.     int returnValue = 0;    // no such entry ENOENT
  1730.     int i;
  1731.     int len;
  1732.     
  1733.     len = strlen(inName);
  1734.     for (i=1; i<=kMaxAttach; i++) {
  1735.         if ( memcmp(inName, &PROJECT_attach[i].kftInterfaceEntry.bsdName[0], len) == 0 ) {
  1736.             returnValue = i;
  1737.             break;
  1738.         }
  1739.     }
  1740.     return returnValue;
  1741. }
  1742.  
  1743. // ---------------------------------------------------------------------------------
  1744. //    Ñ ik_emptyAttachIndex
  1745. // ---------------------------------------------------------------------------------
  1746. //    Find an empty attach instance (available slot)
  1747. //    Return 0 for not found
  1748. static int ik_emptyAttachIndex()
  1749. {
  1750.     int returnValue = 0;    // all slots in use EBUSY
  1751.     int i;
  1752.     
  1753.     for (i=1; i<=kMaxAttach; i++) {
  1754.         if ((PROJECT_attach[i].ipFilterRef == 0) && (PROJECT_attach[i].ifFilterRef == 0)) {
  1755.             returnValue = i;
  1756.             break;
  1757.         }
  1758.     }
  1759.     return returnValue;
  1760. }
  1761.  
  1762. // ---------------------------------------------------------------------------------
  1763. //    Ñ ik_detachController
  1764. // ---------------------------------------------------------------------------------
  1765. //    detach controller and remove any interface attachments
  1766. //    that are no longer referenced.  Finally, clear the control instance.
  1767. //
  1768. //    return 0 for success or unix error code
  1769. static int ik_detachController(int controlIndex)
  1770. {
  1771.     int returnValue=0;
  1772.     int attachIndex;
  1773.     int result;
  1774.     do {
  1775.         if (!controlIndex) break;    // no control instance, we're done
  1776.         // make sure delay table is empty before detaching from any interfaces
  1777.         KFT_delayAge(0);                
  1778.         // if controller was monitoring, turn it off
  1779.         // - user might quit app without stopping or closing monitor window
  1780.         if (PROJECT_control[controlIndex].monitorOn) {
  1781.             PROJECT_control[controlIndex].monitorOn = 0;
  1782.             // bump timer ref count
  1783.             //PROJECT_timerRefCount -= 1;
  1784.             //if (PROJECT_timerRefCount < 0) PROJECT_timerRefCount = 0;
  1785.             result = OSAddAtomic(-1, (SInt32*)&PROJECT_timerRefCount);
  1786.             if (result <= 0) PROJECT_timerRefCount = 0;    // defensive
  1787.         }
  1788.         // get corresponding attach instances
  1789.         for (attachIndex=1;attachIndex<=kMaxAttach;attachIndex++) {
  1790.             if (PROJECT_control[controlIndex].attachMap[attachIndex]) {
  1791.                 // remove our reference to attach instance
  1792.                 PROJECT_control[controlIndex].attachMap[attachIndex] = 0;            
  1793.                 // are there any more references?
  1794.                 if (ik_controlCount(attachIndex) == 0) {
  1795.                     // no more references to this attach instance
  1796.                     // detach our NKE from this interface and clear instance
  1797.                     if (PROJECT_attach[attachIndex].ifFilterRef || PROJECT_attach[attachIndex].ipFilterRef) {
  1798.                         ik_detachInterface(attachIndex);
  1799.                     }
  1800.                 }
  1801.             }    // end found attach instance
  1802.         }    // end for each attach instance
  1803.         // clear control instance
  1804.         bzero(&PROJECT_control[controlIndex], sizeof(control_t));
  1805.     } while (FALSE);
  1806.     return returnValue;
  1807. }
  1808.  
  1809.  
  1810. // ---------------------------------------------------------------------------------
  1811. //    Ñ ik_detachInterface
  1812. // ---------------------------------------------------------------------------------
  1813. //    detach interface and clear the attach instance
  1814. //    return 0 for success or unix error code
  1815. static int ik_detachInterface(int attachIndex)
  1816. {
  1817.     int returnValue=0;
  1818.     errno_t status;
  1819.     int i;
  1820.     do {
  1821.         if ((attachIndex == 0) || (attachIndex > kMaxAttach)) break;    // no attach instance, we're done
  1822.         // for each control instance
  1823.         for (i=1; i<=kMaxControl; i++) {
  1824.             // dis-associate with this attach instance
  1825.             PROJECT_control[i].attachMap[attachIndex] = 0;
  1826.         }
  1827.         // detach our NKE from this interface and clear instance
  1828.             // ifnet_ref
  1829.             // release and set to zero before dlil_detach_filter which calls ipk_ipf_detach_func
  1830.         if (PROJECT_attach[attachIndex].ifnet_ref) ifnet_release(PROJECT_attach[attachIndex].ifnet_ref);
  1831.         PROJECT_attach[attachIndex].ifnet_ref = 0;
  1832.             // ifFilterRef
  1833.         if (PROJECT_attach[attachIndex].ifFilterRef) iflt_detach(PROJECT_attach[attachIndex].ifFilterRef);
  1834.             // ipFilterRef
  1835.         if (PROJECT_attach[attachIndex].ipFilterRef) {
  1836.             status = ipf_remove(PROJECT_attach[attachIndex].ipFilterRef);
  1837.             if (status) {
  1838.                 printf("ik_detachInterface: ipf_remove failed %d\n", status);
  1839.                 returnValue = KERN_FAILURE;
  1840.             }
  1841.         }
  1842.         bzero(&PROJECT_attach[attachIndex], sizeof(attach_t));
  1843.     } while (0);
  1844.     return returnValue;
  1845. }
  1846.  
  1847. // ---------------------------------------------------------------------------------
  1848. //    Ñ PROJECT_modifyReadyPacket
  1849. // ---------------------------------------------------------------------------------
  1850. // Tiger: prepare packet to be modified by finalizing and setting appropriate mbuf flags, return 0
  1851. // Panther: return 1 if outbound hardware TCP checksum is enabled so calculation should be skipped
  1852. // (no easy way to "finalize" in Panther)
  1853. int PROJECT_modifyReadyPacket(KFT_packetData_t* packet)
  1854. {
  1855.     int returnValue = 0;
  1856.     mbuf_t mbuf_ref;
  1857. #if TIGER
  1858.     if (packet->modifyReady == 0) {
  1859.         mbuf_ref = *(packet->mbuf_ptr);
  1860.         if (packet->direction == kDirectionInbound) {
  1861.             mbuf_inbound_modified(mbuf_ref);
  1862.         }
  1863.         else {
  1864.             mbuf_outbound_finalize(mbuf_ref, AF_INET, packet->ipOffset);
  1865.             #if 1
  1866.                 mbuf_csum_request_flags_t request;
  1867.                 u_int32_t value;
  1868.                 mbuf_get_csum_requested(mbuf_ref, &request, &value);
  1869.                 // work around bug in 10.4.2
  1870.                 if (request & 0x1000) returnValue = 1;
  1871.                 if (request & MBUF_CSUM_REQ_TCP) returnValue = 1;
  1872.                 //KFT_logText("csum_requested ", &request);
  1873.             #endif
  1874.         }
  1875.         // remember what we did
  1876.         packet->modifyReady = 1;
  1877.     }
  1878. #else
  1879.     mbuf_ref = *(packet->mbuf_ptr);
  1880.     if (packet->direction == kDirectionInbound) {
  1881.         // invalidate HW generated checksum flags
  1882.         mbuf_ref->m_pkthdr.csum_data = 0;
  1883.         mbuf_ref->m_pkthdr.csum_flags = 0;
  1884.         //if ((mbuf_ref->m_pkthdr.csum_flags & CSUM_TCP_SUM16) &&
  1885.         //    (mbuf_ref->m_pkthdr.csum_flags & CSUM_DATA_VALID)) returnValue = 1;
  1886.     }
  1887.     else {
  1888.         // Notice for outgoing packets the tcp checksum may not include the TCP header yet
  1889.         if (mbuf_ref->m_pkthdr.csum_flags & CSUM_TCP_SUM16) returnValue = 1;
  1890.     }
  1891. #endif
  1892.     return returnValue;
  1893. }
  1894.  
  1895. // ---------------------------------------------------------------------------------
  1896. //    Ñ PROJECT_mtag
  1897. // ---------------------------------------------------------------------------------
  1898. // Tag this packet with "tag_value" so we'll know if we have seen it.
  1899. // tag_value will normally be either TAG_IN or TAG_OUT.
  1900. //
  1901. // Notice if an mbuf is re-used to send a response such as an echo request (ping) that
  1902. // is converted to an echo reply, or simply IP Forwarded back out another interface,
  1903. // you may want to recognize the redirected mbuf as a new packet.
  1904. // Thus we distinguish TAG_IN from TAG_OUT and intentionally replace the
  1905. // previous tag value rather than combining.  If we re-direct a packet, we need to
  1906. // re-tag it accordingly. The code below checks for an existing tag and resets the value.
  1907. //
  1908. // Finally, an mbuf tag is effectively another mbuf that travels with the packet.
  1909. // Allocating an mbuf tag can fail in which case we return the corresponding error code.
  1910. // Notice it is the callers responsibility to free the original packet to avoid looping
  1911. // or a recursive lock attempt (kernel panic) if a packet without the correct
  1912. // tag is re-injected and processed again.
  1913. //
  1914. errno_t PROJECT_mtag(mbuf_t mbuf_ref, int tag_value)
  1915. {
  1916.     errno_t status;
  1917.     int *tag_ref;
  1918.     size_t len;
  1919.     // look for existing tag
  1920.     status = mbuf_tag_find(mbuf_ref, gidtag, MY_TAG_TYPE, &len, (void*)&tag_ref);
  1921.     // allocate tag if needed
  1922.     if (status != 0) {
  1923.         status = mbuf_tag_allocate(mbuf_ref, gidtag, MY_TAG_TYPE, sizeof(*tag_ref), MBUF_DONTWAIT, (void**)&tag_ref);
  1924.         if (status == 0) *tag_ref = 0;
  1925.     }
  1926.     //if (status == 0) *tag_ref = tag_value;
  1927.     if (status == 0) {
  1928.         if (tag_value < 3) *tag_ref &= ~3;    // clear previous TAG_IN or TAG_OUT
  1929.         *tag_ref |= tag_value;
  1930.     }
  1931.     return status;
  1932. }
  1933.  
  1934. // ---------------------------------------------------------------------------------
  1935. //    Ñ PROJECT_is_mtag
  1936. // ---------------------------------------------------------------------------------
  1937. // Return 1 if packet is tagged with "tag_value", otherwise 0
  1938. int PROJECT_is_mtag(mbuf_t mbuf_ref, int tag_value)
  1939. {
  1940.     int returnValue = 0;
  1941.     errno_t status;
  1942.     int *tag_ref;
  1943.     size_t len;
  1944.     // Check whether we have seen this packet before.
  1945.     status = mbuf_tag_find(mbuf_ref, gidtag, MY_TAG_TYPE, &len, (void**)&tag_ref);
  1946.     if ((status == 0) && (*tag_ref & tag_value)) returnValue = 1;
  1947.     return returnValue;
  1948. }
  1949.  
  1950.