home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / WATTCP / MCAST.ZIP / MCAST.DIF next >
Encoding:
Text File  |  1993-11-10  |  23.8 KB  |  884 lines

  1. *** apps/makefile    Tue Nov 09 00:51:06 1993
  2. --- apps/makefile    Wed Nov 10 02:31:48 1993
  3. ***************
  4. *** 13,22 ****
  5.   #
  6.   
  7.   !if '$(DEBUG)'=='E'
  8. ! IDEBUG=-v
  9.   TEXTDEBUG=enabled
  10.   !elif '$(DEBUG)'=='D'
  11. ! IDEBUG=-v-
  12.   TEXTDEBUG=disabled
  13.   #!else
  14.   #!error  DEBUG must be set to either E or D
  15. --- 13,22 ----
  16.   #
  17.   
  18.   !if '$(DEBUG)'=='E'
  19. ! IDEBUG=-v -DMULTICAST
  20.   TEXTDEBUG=enabled
  21.   !elif '$(DEBUG)'=='D'
  22. ! IDEBUG=-v- -DMULTICAST
  23.   TEXTDEBUG=disabled
  24.   #!else
  25.   #!error  DEBUG must be set to either E or D
  26. ***************
  27. *** 49,55 ****
  28.   
  29.   exes.arc: ping.exe daytime.exe finger.exe lpr.exe lpq.exe \
  30.           tcpport.exe rexec.exe ntime.exe tcpinfo.exe cookie.exe \
  31. !         popdump.exe ph.exe tcptalk.exe
  32.   # host.exe
  33.           echo done $(TEXTMODEL) make with debugging $(TEXTDEBUG)
  34.   
  35. --- 49,55 ----
  36.   
  37.   exes.arc: ping.exe daytime.exe finger.exe lpr.exe lpq.exe \
  38.           tcpport.exe rexec.exe ntime.exe tcpinfo.exe cookie.exe \
  39. !         popdump.exe ph.exe tcptalk.exe lister.exe blather.exe
  40.   # host.exe
  41.           echo done $(TEXTMODEL) make with debugging $(TEXTDEBUG)
  42.   
  43. ***************
  44. *** 92,97 ****
  45. --- 92,103 ----
  46.   
  47.   tcptalk.exe: tcptalk.c
  48.           $(CC)  tcptalk.c $(CLIB)
  49. + lister.exe: lister.c
  50. +         $(CC)  lister.c $(CLIB)
  51. + blather.exe: blather.c
  52. +         $(CC)  blather.c $(CLIB)
  53.   
  54.   host.exe: host.c
  55.           $(CC)  host.c $(CLIB)
  56. *** include/tcp.h    Thu Aug 05 10:13:58 1993
  57. --- include/tcp.h    Tue Nov 09 23:26:36 1993
  58. ***************
  59. *** 281,284 ****
  60. --- 281,293 ----
  61.   extern int addwattcpd( void (*p)() );
  62.   extern int delwattcpd( void (*p)() );
  63.   extern int tap_add( void *socket, void *userid );
  64. + #if defined(MULTICAST)
  65. + /* Stuff for Multicast Support - JRM 6/7/93 */
  66. + extern int udp_SetTTL(udp_Socket *, byte );
  67. + extern int join_mcast_group( longword );
  68. + extern int leave_mcast_group( longword );
  69. + #endif /* MULTICAST */
  70.   #endif /* WTCP_VER */
  71. *** include/wattcp.h    Thu Jul 15 11:16:48 1993
  72. --- include/wattcp.h    Tue Nov 09 23:38:10 1993
  73. ***************
  74. *** 17,22 ****
  75. --- 17,26 ----
  76.   
  77.   #include <stdio.h>
  78.   #include <elib.h>
  79. + #if defined(MULTICAST)
  80. + #include <stdlib.h>
  81. + #include <time.h>
  82. + #endif /* MULTICAST */
  83.   
  84.   #define set_mstimeout( x ) (set_timeout(0)+ (x / 55))
  85.   
  86. ***************
  87. *** 45,50 ****
  88. --- 49,57 ----
  89.   #define UDP_PROTO  0x11
  90.   #define TCP_PROTO  0x06
  91.   #define ICMP_PROTO 0x01
  92. + #if defined(MULTICAST)
  93. + #define    IGMP_PROTO 0x02
  94. + #endif /* MULTICAST */
  95.   
  96.   #define TCP_MODE_BINARY  0       /* default mode */
  97.   #define TCP_MODE_ASCII   1
  98. ***************
  99. *** 74,79 ****
  100. --- 81,90 ----
  101.   
  102.   extern word sock_inactive;      /* in pcbootp.c */
  103.   extern word _pktdevclass;
  104. + #if defined(MULTICAST)
  105. + extern byte _pktdevlevel;
  106. + extern byte pkterror;
  107. + #endif /* MULTICAST */
  108.   extern word _mss;
  109.   extern word _bootptimeout;    /* in pcbootp.c */
  110.   extern longword _bootphost;    /* in pcbootp.c */
  111. ***************
  112. *** 102,107 ****
  113. --- 113,132 ----
  114.       longword        destination;
  115.   } in_Header;
  116.   
  117. + #if defined(MULTICAST)
  118. + /* The Internet Group Management Protocol (IGMP) Packet */
  119. + typedef struct {
  120. +     unsigned       type         : 4;
  121. +     unsigned       version   : 4;
  122. +     byte       mbz;
  123. +     word       checksum;
  124. +     longword       address;
  125. + } IGMP_packet;
  126. + #define IGMP_Version  1
  127. + #define IGMP_Query    1
  128. + #define IGMP_Report   2
  129. + #endif /* MULTICAST */
  130.   
  131.   #define in_GetVersion(ip) ( (ip)->ver )
  132.   #define in_GetHdrlen(ip)  ( (ip)->hdrlen )  /* 32 bit word size */
  133. ***************
  134. *** 179,184 ****
  135. --- 204,212 ----
  136.   typedef struct _udp_socket {
  137.       struct _udp_socket *next;
  138.       word        ip_type;        /* always set to UDP_PROTO */
  139. + #if defined(MULTICAST)
  140. +     byte        ttl;        /* mainly for use with multicast */
  141. + #endif /* MULTICAST */
  142.       char       *err_msg;        /* null when all is ok */
  143.       char           *usr_name;
  144.       void      (*usr_yield)();
  145. ***************
  146. *** 425,427 ****
  147. --- 453,508 ----
  148.   extern int tcp_listen(tcp_Socket *s, word lport, longword ina, word port, procref datahandler, word timeout);
  149.   extern int sock_gets(sock_type *, byte *, int );
  150.   extern int sock_close(sock_type * );
  151. + #if defined(MULTICAST)
  152. + /* Stuff for Multicast Support - JRM 6/7/93 */
  153. + extern int udp_SetTTL(udp_Socket *, byte );
  154. + extern int join_mcast_group( longword );
  155. + extern int leave_mcast_group( longword );
  156. + extern int _eth_join_mcast_group( int );
  157. + extern int _eth_leave_mcast_group( int );
  158. + extern int is_multicast( longword );
  159. + extern int multi_to_eth( longword , eth_address );
  160. + extern void igmp_handler( in_Header * );
  161. + extern int igmp_report( longword );
  162. + extern int _pkt_set_rcv_mode( int , int );
  163. + extern int _pkt_get_rcv_mode( int );
  164. + extern int _pkt_get_multicast_list( byte , eth_address * );
  165. + extern int _pkt_set_multicast_list( byte , eth_address * );
  166. + extern int _pkt_get_ip_rcv_mode( );
  167. + extern int _pkt_set_ip_rcv_mode( int );
  168. + #define CLASS_D_MASK 0xE0000000  /* the mask that defines IP Class D */
  169. + #define IPMULTI_MASK 0x007FFFFF  /* to get the low-order 23 bits */
  170. + #define ETH_MULTI 0x01005E       /* high order bits of multi eth addr */
  171. + #define IPMULTI_SIZE 20         /* the size of the ipmulti table */
  172. + #define ALL_SYSTEMS 0xE0000001     /* the default mcast addr 224.0.0.1 */
  173. + typedef struct {
  174. +     longword    ina;        /* IP address of group */
  175. +     eth_address    ethaddr;    /* Ethernet address of group */
  176. +     byte        processes;    /* number of interested processes */
  177. +     time_t        replytime;    /* IGMP query reply timer */
  178. +     byte        active;        /* is this an active entry */
  179. + } multicast;
  180. + extern multicast _ipmulti[IPMULTI_SIZE];
  181. + /* PD Error Returns */
  182. + #define BASIC_DVR    0
  183. + #define BAD_HANDLE    1
  184. + #define NO_CLASS    2
  185. + #define NO_TYPE        3
  186. + #define NO_NUMBER    4
  187. + #define BAD_TYPE    5
  188. + #define NO_MULTICAST    6
  189. + #define CANT_TERMINATE    7
  190. + #define BAD_MODE    8
  191. + #define NO_SPACE    9
  192. + #define TYPE_INUSE    10
  193. + #define BAD_COMMAND    11
  194. + #define CANT_SEND    12
  195. + #define CANT_SET    13
  196. + #define BAD_ADDRESS    14
  197. + #endif /* MULTICAST */
  198. *** src/makefile    Tue Nov 09 00:51:34 1993
  199. --- src/makefile    Tue Nov 09 23:42:34 1993
  200. ***************
  201. *** 7,13 ****
  202.   #    TRACE        - turn on tracing/debugging code
  203.   #
  204.   #
  205. ! DEBUGS= -v
  206.   
  207.   CFLAGS= $(DEBUGS) -DMSDOS -Ic:\borlandc\include -I..\include -g200
  208.   MODELS=-ms
  209. --- 7,13 ----
  210.   #    TRACE        - turn on tracing/debugging code
  211.   #
  212.   #
  213. ! DEBUGS= -v -DMULTICAST
  214.   
  215.   CFLAGS= $(DEBUGS) -DMSDOS -Ic:\borlandc\include -I..\include -g200
  216.   MODELS=-ms
  217. ***************
  218. *** 37,44 ****
  219.           sock_prn.obj sock_ini.obj pcbsd.obj pcrecv.obj \
  220.           udp_nds.obj udp_dom.obj pcconfig.obj pc_cbrk.obj pcbuf.obj \
  221.           pcbootp.obj sock_dbu.obj pcdbug.obj test.obj pcintr.obj pcstat.obj \
  222. !         bsdname.obj fragment.obj \
  223. !         netback.obj select.obj
  224.   
  225.   ..\lib\wattcpsm.lib: $(objs)
  226.           echo done
  227. --- 37,44 ----
  228.           sock_prn.obj sock_ini.obj pcbsd.obj pcrecv.obj \
  229.           udp_nds.obj udp_dom.obj pcconfig.obj pc_cbrk.obj pcbuf.obj \
  230.           pcbootp.obj sock_dbu.obj pcdbug.obj test.obj pcintr.obj pcstat.obj \
  231. !         bsdname.obj fragment.obj netback.obj select.obj \
  232. !     pcigmp.obj pcmulti.obj
  233.   
  234.   ..\lib\wattcpsm.lib: $(objs)
  235.           echo done
  236. ***************
  237. *** 70,75 ****
  238. --- 70,78 ----
  239.   pcstat.obj: pcstat.c ..\include\wattcp.h
  240.   netback.obj: netback.c ..\include\elib.h ..\include\tcp.h
  241.   bsdname.obj: bsdname.c ..\include\wattcp.h
  242. + pcigmp.obj: pcigmp.c ..\include\wattcp.h
  243. + pcmulti.obj: pcmulti.c ..\include\wattcp.h
  244.   
  245.   
  246.   
  247. *** src/pcpkt.c    Wed Aug 04 11:14:30 1993
  248. --- src/pcpkt.c    Tue Nov 09 23:43:48 1993
  249. ***************
  250. *** 22,32 ****
  251. --- 22,45 ----
  252.   
  253.   #define INT_FIRST 0x60
  254.   #define INT_LAST  0x80
  255. + /* Basic PD Functions */
  256.   #define PD_DRIVER_INFO    0x1ff
  257.   #define PD_ACCESS     0x200
  258.   #define PD_RELEASE    0x300
  259.   #define PD_SEND        0x400
  260. + #define PD_TERMINATE    0x500
  261.   #define PD_GET_ADDRESS    0x600
  262. + #define PD_RESET    0x700
  263. + /* Extended PD Functions */
  264. + #define PD_SET_RCV    0x1400
  265. + #define PD_GET_RCV    0x1500
  266. + #define PD_SET_MULTI    0x1600
  267. + #define PD_GET_MULTI    0x1700
  268. + #define PD_GET_STATS    0x1800
  269. + #define PD_SET_ADDR    0x1900
  270.   #define  CARRY         1         /* carry bit in flags register */
  271.   
  272.   word _pktipofs = 0;            /* offset from header to start of pkt */
  273. ***************
  274. *** 102,107 ****
  275. --- 115,123 ----
  276.       }
  277.       } else {
  278.       pd_type = regs.r_dx;
  279. + #if defined(MULTICAST)
  280. +     _pktdevlevel = (regs.r_ax & 0xff);
  281. + #endif /* MULTICAST */
  282.       switch ( _pktdevclass = (regs.r_cx >> 8)) {
  283.           case PD_ETHER : _pktipofs = 14;
  284.   
  285. ***************
  286. *** 158,163 ****
  287. --- 174,184 ----
  288.       return( 1 );
  289.       }
  290.   
  291. + #if defined(MULTICAST)
  292. +     /* set recieve mode for IP */
  293. +     _pkt_set_ip_rcv_mode( 4 );
  294. + #endif /* MULTICAST */
  295.       return( 0 );
  296.   }
  297.   void pkt_release()
  298. ***************
  299. *** 269,273 ****
  300. --- 290,507 ----
  301.       return( eth_addr );
  302.   }
  303.   
  304. + #if defined(MULTICAST)
  305. + /* 
  306. +  * _pkt_set_rcv_mode - sets the recieve mode of the interface
  307. +  *
  308. +  * int _pkt_set_rcv_mode( int handle, int mode )
  309. +  * Where:
  310. +  *    handle    is the handle returned by access_type
  311. +  *    mode    is one of the following modes:
  312. +  *        1    turn off reciever
  313. +  *        2    recieve only packets sent to this interface
  314. +  *        3    mode 2 plus broadcast packets <default>
  315. +  *        4    mode 3 plus limited multicast packets
  316. +  *        5    mode 3 plus all multicast packets
  317. +  *        6    all packets (AKA promiscuous mode )
  318. +  * Returns:
  319. +  *    -1    upon error - pkterror is set
  320. +  *    0    if the mode was set successfully
  321. +  */
  322. + int _pkt_set_rcv_mode( handle, mode )
  323. + int handle;
  324. + int mode;
  325. + {
  326. +     struct REGPACK regs;
  327. +     /* This needs an Extended driver */
  328. +     if ( _pktdevlevel < 2 ){
  329. +         pkterror = BASIC_DVR;
  330. +         return(-1);
  331. +     }
  332. +     regs.r_ax = PD_SET_RCV;
  333. +     regs.r_bx = handle;
  334. +     regs.r_cx = mode;
  335. +         intr( pkt_interrupt, ®s );
  336. +     /* The carry flag indicates an error return */
  337. +         if ( regs.r_flags & CARRY ){
  338. +         pkterror = regs.r_dx >> 8;
  339. +         return( -1 );
  340. +         }
  341. +     return( 0 );
  342. + }
  343. + /* 
  344. +  * _pkt_get_rcv_mode - gets the recieve mode of the interface
  345. +  *
  346. +  * int _pkt_get_rcv_mode( int handle )
  347. +  * Where:
  348. +  *    handle    is the handle returned by access_type
  349. +  *
  350. +  * Returns:
  351. +  *    -1    upon error - pkterror is set
  352. +  *    mode    is one of the following modes: (upon return)
  353. +  *        1    turn off reciever
  354. +  *        2    recieve only packets sent to this interface
  355. +  *        3    mode 2 plus broadcast packets <default>
  356. +  *        4    mode 3 plus limited multicast packets
  357. +  *        5    mode 3 plus all multicast packets
  358. +  *        6    all packets (AKA promiscuous mode )
  359. +  */
  360. + int _pkt_get_rcv_mode( handle )
  361. + int handle;
  362. + {
  363. +     struct REGPACK regs;
  364. +     /* This needs an Extended driver */
  365. +     if ( _pktdevlevel < 2 ){
  366. +         pkterror = BASIC_DVR;
  367. +         return( -1 );
  368. +     }
  369. +     regs.r_ax = PD_GET_RCV;
  370. +     regs.r_bx = handle;
  371. +         intr( pkt_interrupt, ®s );
  372. +     /* The carry flag indicates an error return */
  373. +         if ( regs.r_flags & CARRY ){
  374. +         pkterror = regs.r_dx >> 8;
  375. +         return( -1 );
  376. +         }
  377. +     return( regs.r_ax );
  378. + }
  379. + /*
  380. +  * _pkt_get_multicast_list - gets the current list of multicast addresses
  381. +  *                           from the packet driver
  382. +  *
  383. +  * int _pkt_get_multicast_list( byte len, eth_address *listbuf )
  384. +  * Where:
  385. +  *    len    is the length of listbuf
  386. +  *    listbuf    is the buffer into which the list is placed
  387. +  * Returns:
  388. +  *    -1    upon error - pkterror is set
  389. +  *    len    if retrieval was successful
  390. +  *
  391. +  */
  392. + int _pkt_get_multicast_list( len, listbuf )
  393. + byte len;
  394. + eth_address *listbuf;
  395. + {
  396. +     struct REGPACK regs;
  397. +     /* Basic drivers don't support multicast */
  398. +     if ( _pktdevlevel < 2 ) {
  399. +         pkterror = BASIC_DVR;
  400. +         return( -1 );
  401. +     }
  402. +     regs.r_ax = PD_GET_MULTI;
  403. +         intr( pkt_interrupt, ®s );
  404. +     /* The carry flag indicates an error return */
  405. +         if ( regs.r_flags & CARRY ) {
  406. +         pkterror = regs.r_dx >> 8;
  407. +             return( -1 );
  408. +         }
  409. +     /* move it into the caller's buffer and return happily */
  410. +     len = min( len, regs.r_cx );
  411. +     movedata(regs.r_es, regs.r_di, FP_SEG( listbuf ), FP_OFF( listbuf ),
  412. +         len);
  413. +     return(len);
  414. + }
  415. + /* 
  416. +  * _pkt_set_multicast_list - sets the list of multicast addresses for which
  417. +  *                 the PD is responsible.
  418. +  *
  419. +  * int _pkt_set_multicast_list( byte len, eth_address *listbuf )
  420. +  * Where:
  421. +  *    len    is the length of listbuf
  422. +  *    listbuf    is the buffer containing the list
  423. +  * Returns:
  424. +  *    -1    upon error - pkterror is set
  425. +  *    0    if set was successful
  426. +  */
  427. + _pkt_set_multicast_list( len, listbuf )
  428. + byte len;
  429. + eth_address *listbuf;
  430. + {
  431. +     struct REGPACK regs;
  432. +     /* Basic drivers don't support multicast */
  433. +     if ( _pktdevlevel < 2 ){
  434. +         pkterror = BASIC_DVR;
  435. +         return( -1 );
  436. +     }
  437. +     regs.r_ax = PD_SET_MULTI;
  438. +     regs.r_cx = len;
  439. +     regs.r_es = FP_SEG( listbuf );
  440. +     regs.r_di = FP_OFF( listbuf );
  441. +         intr( pkt_interrupt, ®s );
  442. +     /* The carry flag indicates an error return */
  443. +         if ( regs.r_flags & CARRY ){
  444. +         pkterror = regs.r_dx >> 8;
  445. +         return( -1 );
  446. +         }
  447. +     return( 0 );
  448. + }
  449. + /* 
  450. +  * _pkt_get_ip_rcv_mode - gets the recieve mode of the interface for
  451. +  *              the IP handle
  452. +  *
  453. +  * int _pkt_get_ip_rcv_mode( )
  454. +  * Returns:
  455. +  *    -1    if the request failed - pkterror is set
  456. +  *    mode    is one of the following modes: (upon return)
  457. +  *        1    turn off reciever
  458. +  *        2    recieve only packets sent to this interface
  459. +  *        3    mode 2 plus broadcast packets <default>
  460. +  *        4    mode 3 plus limited multicast packets
  461. +  *        5    mode 3 plus all multicast packets
  462. +  *        6    all packets (AKA promiscuous mode )
  463. +  */
  464.   
  465. + int _pkt_get_ip_rcv_mode()
  466. + {
  467. +     return( _pkt_get_rcv_mode(pkt_ip_handle));
  468. + }
  469. + /* 
  470. +  * _pkt_set_ip_rcv_mode - sets the recieve mode of the interface for
  471. +  *              the IP handle
  472. +  *
  473. +  * int _pkt_set_ip_rcv_mode( int mode )
  474. +  * Where:
  475. +  *    mode    is one of the following modes: (upon return)
  476. +  *        1    turn off reciever
  477. +  *        2    recieve only packets sent to this interface
  478. +  *        3    mode 2 plus broadcast packets <default>
  479. +  *        4    mode 3 plus limited multicast packets
  480. +  *        5    mode 3 plus all multicast packets
  481. +  *        6    all packets (AKA promiscuous mode )
  482. +  * Returns:
  483. +  *    -1    if the request failed - pkterror is set
  484. +  *    0    mode set was successful
  485. +  */
  486. + int _pkt_set_ip_rcv_mode( mode )
  487. + int mode;
  488. + {
  489. +     return( _pkt_set_rcv_mode(pkt_ip_handle, mode));
  490. + }
  491. + #endif /* MULTICAST */
  492.                                
  493. *** src/pcsed.c    Thu Jul 15 11:15:56 1993
  494. --- src/pcsed.c    Tue Nov 09 23:43:48 1993
  495. ***************
  496. *** 19,28 ****
  497. --- 19,35 ----
  498.   #include <wattcp.h>
  499.   #include <ethdev.h>
  500.   #include <mem.h>
  501. + #if defined(MULTICAST)
  502. + #include <dos.h>
  503. + #endif
  504.   
  505.   eth_address _eth_addr;        /* local ethernet address */
  506.   eth_address _eth_brdcast;    /* Ethernet broadcast address */
  507.   word _pktdevclass = 1;        /* Ethernet = 1, SLIP = 6 */
  508. + #if defined(MULTICAST)
  509. + byte  _pktdevlevel = 1;        /* assume basic unless otherwise specified */
  510. + byte pkterror;
  511. + #endif /* MULTICAST */
  512.   
  513.   /*
  514.    *  Initialize the Ethernet Interface, and this package.  Enable input on
  515. ***************
  516. *** 117,120 ****
  517. --- 124,264 ----
  518.   {
  519.       return( p - 8 );
  520.   }
  521. + #if defined(MULTICAST)
  522. + /*
  523. +  * _eth_join_mcast_group - joins a multicast group (at the physical layer)
  524. +  *
  525. +  * int _eth_join_mcast_group( int entry )
  526. +  * Where:
  527. +  *    entry    the entry # in the _ipmulti table
  528. +  * Returns:
  529. +  *    1    if the group was joined successfully
  530. +  *    0    if attempt failed
  531. +  */
  532. + int _eth_join_mcast_group( entry )
  533. + int entry;
  534. + {
  535. +     eth_address list[IPMULTI_SIZE];
  536. +     int mode;
  537. +     int i;
  538. +     byte len;
  539. +     byte nextentry = 0;
  540. +     /* initialize a few things */
  541. +     _ipmulti[entry].active = 0;
  542. +     _ipmulti[entry].replytime = time(NULL);
  543. +     _ipmulti[entry].processes = 1;
  544. +     /* Fill in the hardware address */
  545. +     if( ! multi_to_eth( _ipmulti[entry].ina, _ipmulti[entry].ethaddr ))
  546. +         return( 0 );    /* can't convert it */
  547. +     mode=_pkt_get_ip_rcv_mode();
  548. +     if( mode == -1 )    /* something seems to be broken */
  549. +         return( 0 );
  550. +     else if ( mode == 5 ) {    /* we are in all mcast mode, so don't bother */
  551. +         _ipmulti[entry].active = 1;
  552. +         return( 1 );
  553. +     }
  554. +     if( (len = _pkt_get_multicast_list( sizeof list, &list[0] )) == -1)
  555. +         return( 0 );
  556. +     /* check to see if the address is already in the list */
  557. +     for (i = 0; i< (len/sizeof list[0]); i++){
  558. +         if( !memcmp(list[i],_ipmulti[entry].ethaddr,sizeof list[0])){
  559. +             _ipmulti[entry].active = 1;
  560. +             return(1);
  561. +         }
  562. +     }
  563. +     if ( len )
  564. +         nextentry = len / (sizeof list[0]);
  565. +     movedata(FP_SEG(_ipmulti[entry].ethaddr),FP_OFF(_ipmulti[entry].ethaddr),
  566. +          FP_SEG(&list[nextentry]),FP_OFF(&list[nextentry]), 6);
  567. +     len+= sizeof list[0];
  568. +     if( _pkt_set_multicast_list( len, &list[0] ) == -1)
  569. +         if( pkterror == NO_SPACE ){    /* out of space, switch mode */
  570. +             if( _pkt_set_ip_rcv_mode( 5 ) == -1 )
  571. +                 return( 0 );
  572. +         } else
  573. +             return( 0 );
  574. +     _ipmulti[entry].active = 1;
  575. +     return( 1 );
  576. + }
  577. + /* 
  578. +  * _eth_leave_mcast_group - leaves a multicast group (at the physical layer)
  579. +  *
  580. +  * int _eth_leave_mcast_group( int entry )
  581. +  * Where:
  582. +  *    entry    the entry # in the _ipmulti table
  583. +  * Returns:
  584. +  *    1    if the group was left successfully
  585. +  *    0    if attempt failed
  586. +  */
  587. + int _eth_leave_mcast_group( entry )
  588. + int entry;
  589. + {
  590. +     eth_address list[IPMULTI_SIZE];
  591. +     int mode;
  592. +     int i;
  593. +     int ethindex = -1;
  594. +     byte len;
  595. +     /* NOTE: This should be expanded to include switching back to mode 4
  596. +        if the list of multicast addresses has shrunk sufficiently */
  597. +     /* First check to see if we're in mode 5. if so, mark the entry
  598. +        as inactive and return */
  599. +     mode=_pkt_get_ip_rcv_mode();
  600. +     if( mode == -1 )    /* something seems to be broken */
  601. +         return( 0 );
  602. +     else if ( mode == 5 ) {    /* we are in all mcast mode, so don't bother */
  603. +         _ipmulti[entry].active = 0;
  604. +         return( 1 );
  605. +     }
  606. +     /* get the list of current multicast addresses */
  607. +     if( (len = _pkt_get_multicast_list( sizeof list, &list[0] )) == -1)
  608. +         return( 0 );
  609. +     /* find the apropriate entry */
  610. +     for (i = 0; i< (len/(sizeof list[0])); i++)
  611. +         if( !memcmp(list[i],_ipmulti[entry].ethaddr,sizeof list[0]))
  612. +             ethindex = i;
  613. +     /* if it's not in the list, just set the entry inactive and return */
  614. +     if ( ethindex == -1 ){
  615. +         _ipmulti[entry].active = 0;
  616. +         return( 1 );
  617. +     }
  618. +     /* ahh, but it _is_ in the list. So shorten the list and send it
  619. +        back to the PD */
  620. +     if( ethindex+1 < (len/(sizeof list[0]))){
  621. +         movedata(FP_SEG(&list[ethindex+1]),FP_OFF(&list[ethindex+1]),
  622. +                  FP_SEG(&list[ethindex]),FP_OFF(&list[ethindex]),
  623. +                  len - ((ethindex+1)*(sizeof list[0])));
  624. +     }
  625. +     len -= sizeof list[0];
  626. +     if( _pkt_set_multicast_list( len, &list[0] ) == -1)
  627. +         if( pkterror == NO_SPACE ){    /* out of space, switch mode */
  628. +             if( _pkt_set_ip_rcv_mode( 5 ) == -1 )
  629. +                 return( 0 );
  630. +         } else
  631. +             return( 0 );
  632. +     _ipmulti[entry].active = 0;
  633. +     return( 1 );
  634. + }
  635. + #endif /* MUTICAST */
  636.   
  637. *** src/pctcp.c    Thu Sep 30 13:47:42 1993
  638. --- src/pctcp.c    Wed Nov 10 01:48:12 1993
  639. ***************
  640. *** 293,299 ****
  641. --- 293,308 ----
  642.       /* check for broadcast */
  643.       if ( (long)(ina) == -1 || !ina )
  644.       memset( s->hisethaddr, 0xff, sizeof( eth_address ));
  645. + #if defined(MULTICAST)
  646. +     else  /* check for multicast */
  647. +     if ( is_multicast( ina )){
  648. +     if ( ! multi_to_eth( ina, &s->hisethaddr[0] ))
  649. +         return( 0 );
  650. +     s->ttl = 1;    /* so we don't send worldwide as default */
  651. +     } else if ( ! _arp_resolve(ina, &s->hisethaddr[0], 0) )
  652. + #else
  653.       else if ( ! _arp_resolve(ina, (eth_address *) &s->hisethaddr[0], 0) )
  654. + #endif
  655.       return( 0 );
  656.   
  657.       s->hisaddr = ina;
  658. ***************
  659. *** 306,312 ****
  660. --- 315,339 ----
  661.       return( 1 );
  662.   }
  663.   
  664. + #if defined(MULTICAST)
  665.   /*
  666. +  * Set the TTL on an outgoing UDP datagram.
  667. +  * udp_SetTTL(udp_Socket *s, byte ttl)
  668. +  * where:
  669. +  *    s    the socket of the UDP connection (?!?) in question
  670. +  *    ttl    the desired ttl for the outgoing datagrams
  671. +  */
  672. + int udp_SetTTL( s, ttl )
  673. + udp_Socket *s;
  674. + byte ttl;
  675. + {
  676. +     s->ttl = ttl;
  677. +     return( 1 );
  678. + }
  679. + #endif /* MULTICAST */
  680. + /*
  681.    * Actively open a TCP connection to a particular destination.
  682.    *    - 0 on error
  683.    */
  684. ***************
  685. *** 595,600 ****
  686. --- 622,630 ----
  687.       static longword timeout = 0;
  688.       static longword start = 0;
  689.   
  690. + #if defined(MULTICAST)
  691. +     int i;
  692. + #endif /* MULTICAST */
  693.       int x;
  694.       int packettype;
  695.   
  696. ***************
  697. *** 631,636 ****
  698. --- 661,671 ----
  699.               case ICMP_PROTO :
  700.               icmp_handler(ip);
  701.               break;
  702. + #if defined(MULTICAST)
  703. +             case IGMP_PROTO :
  704. +             igmp_handler(ip);
  705. +             break;
  706. + #endif
  707.           }
  708.           } else  {
  709.           if (debug_on)
  710. ***************
  711. *** 649,654 ****
  712. --- 684,702 ----
  713.       /* check for our outstanding packets */
  714.       tcp_Retransmitter();
  715.   
  716. + #if defined(MULTICAST)
  717. +     /* check to see if we owe any IGMP Reports */
  718. +     for(i=0; i < IPMULTI_SIZE ; i++){
  719. +         if( _ipmulti[i].active &&
  720. +         ( _ipmulti[i].ina != ALL_SYSTEMS ) &&
  721. +         ( _ipmulti[i].replytime ) &&
  722. +             ( _ipmulti[i].replytime <= time(NULL) )){
  723. +                 igmp_report(_ipmulti[i].ina);
  724. +             _ipmulti[i].replytime = 0;
  725. +             }
  726. +     }
  727. + #endif /* MULTICAST */
  728.       return( s->udp.ip_type );
  729.   }
  730.   
  731. ***************
  732. *** 700,706 ****
  733. --- 748,758 ----
  734.   /* inp->vht = 0x4500;*/   /* version 4, hdrlen 5, tos 0 */
  735.       inp->identification = intel16( ++ip_id );   /* was post inc */
  736.   //    inp->frag = 0;
  737. + #if defined(MULTICAST)
  738. +     inp->ttl = s->ttl ? s->ttl : 254 ; /* if set, us it. Otherwise 254 */
  739. + #else
  740.       inp->ttl = 254;
  741. + #endif
  742.       inp->proto = UDP_PROTO;    /* udp */
  743.   /* inp->ttlProtocol = (250<<8) + 6; */
  744.       inp->checksum = 0;
  745. ***************
  746. *** 912,922 ****
  747.   
  748.       temp = intel( ip->destination );
  749.   
  750.       if ( ((~temp & ~sin_mask) != 0) &&  /* not a broadcast packet*/
  751.           ((( temp - my_ip_addr) > multihomes )   /* not my address */
  752.           && my_ip_addr))                 /* and I know my address */
  753.             return;
  754.   
  755.       len = in_GetHdrlenBytes(ip);
  756.       up = (udp_Header *)((byte *)ip + len);    /* udp segment pointer */
  757. --- 964,980 ----
  758.   
  759.       temp = intel( ip->destination );
  760.   
  761. + #if defined(MULTICAST)
  762. + /* This is the only really gross hack in the multicasting stuff.
  763. +  * I'll fix it as soon as I can figure out what I want to do here.
  764. +  * -JRM 8/1/93
  765. +  */
  766. + #else
  767.       if ( ((~temp & ~sin_mask) != 0) &&  /* not a broadcast packet*/
  768.           ((( temp - my_ip_addr) > multihomes )   /* not my address */
  769.           && my_ip_addr))                 /* and I know my address */
  770.             return;
  771. ! #endif /* MULTICAST */
  772.   
  773.       len = in_GetHdrlenBytes(ip);
  774.       up = (udp_Header *)((byte *)ip + len);    /* udp segment pointer */
  775. ***************
  776. *** 949,954 ****
  777. --- 1007,1027 ----
  778.           break;
  779.           }
  780.       }
  781. + #if defined(MULTICAST)
  782. +     if ( !s ) {
  783. +     /* demux to multicast sockets */
  784. +     for ( s = udp_allsocs; s; s = s->next ){
  785. +         if ( s->hisport != 0 &&
  786. +          s->hisaddr == intel( ip->destination ) &&
  787. +          intel16( up->dstPort ) == s->myport &&
  788. +          is_multicast( intel( ip->destination ))){
  789. +              break;
  790. +          }
  791. +     }
  792. +     }
  793. + #endif /* MULTICAST */
  794.       if ( !s ) {
  795.       /* demux to broadcast sockets */
  796.       for ( s = udp_allsocs; s; s = s->next )
  797. *** src/sock_ini.c    Thu Oct 22 17:26:16 1992
  798. --- src/sock_ini.c    Tue Nov 09 23:43:48 1993
  799. ***************
  800. *** 37,40 ****
  801. --- 37,47 ----
  802.           if ( !_survivebootp )
  803.           exit( 3 );
  804.       }
  805. + #if defined(MULTICAST)
  806. +     /* to initialize the random number generator */
  807. +     randomize();
  808. +     /* all multicast level 2 systems must join at startup */
  809. +     join_mcast_group(ALL_SYSTEMS);
  810. + #endif /* MULTICAST */
  811.   }
  812.