Example #1
0
DWORD DSLeaseIpAddress( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
    COMM_DHCP_REPLY Reply;
    PDHCP_ADAPTER Adapter;
    struct protocol* proto;

    ApiLock();

    Adapter = AdapterFindIndex( Req->AdapterIndex );

    Reply.Reply = Adapter ? 1 : 0;

    if( Adapter ) {
        proto = find_protocol_by_adapter( &Adapter->DhclientInfo );
        if (proto)
            remove_protocol(proto);

        add_protocol( Adapter->DhclientInfo.name,
                      Adapter->DhclientInfo.rfdesc, got_one,
                      &Adapter->DhclientInfo );

        Adapter->DhclientInfo.client->state = S_INIT;
        state_reboot(&Adapter->DhclientInfo);

        if (AdapterStateChangedEvent != NULL)
            SetEvent(AdapterStateChangedEvent);
    }

    ApiUnlock();

    return Send( &Reply );
}
Example #2
0
static void remove_all_protocols(void)
{
	NetProtocol *n = (NetProtocol *)prot_list.lh_Head, *next;
	while ((next = (NetProtocol *)n->ln_Succ) != NULL) {
		remove_protocol(n);
		n = next;
	}
}
Example #3
0
void
got_one(struct protocol *l)
{
	struct sockaddr_in from;
	struct hardware hfrom;
	struct iaddr ifrom;
	ssize_t result;
	union {
		/*
		 * Packet input buffer.  Must be as large as largest
		 * possible MTU.
		 */
		unsigned char packbuf[4095];
		struct dhcp_packet packet;
	} u;
	struct interface_info *ip = l->local;

	if ((result = receive_packet(ip, u.packbuf, sizeof(u), &from,
	    &hfrom)) == -1) {
		warning("receive_packet failed on %s: %s", ip->name,
		    strerror(errno));
		ip->errors++;
		if ((!interface_status(ip)) ||
		    (ip->noifmedia && ip->errors > 20)) {
			/* our interface has gone away. */
			warning("Interface %s no longer appears valid.",
			    ip->name);
			ip->dead = 1;
			interfaces_invalidated = 1;
			close(l->fd);
			remove_protocol(l);
			free(ip);
		}
		return;
	}
	if (result == 0)
		return;

	if (bootp_packet_handler) {
		ifrom.len = 4;
		memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len);

		(*bootp_packet_handler)(ip, &u.packet, result,
		    from.sin_port, ifrom, &hfrom);
	}
}
Example #4
0
DWORD DSStaticRefreshParams( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
    NTSTATUS Status;
    COMM_DHCP_REPLY Reply;
    PDHCP_ADAPTER Adapter;
    struct protocol* proto;

    ApiLock();

    Adapter = AdapterFindIndex( Req->AdapterIndex );

    Reply.Reply = Adapter ? 1 : 0;

    if( Adapter ) {
        if (Adapter->NteContext)
        {
            DeleteIPAddress( Adapter->NteContext );
            Adapter->NteContext = 0;
        }
        if (Adapter->RouterMib.dwForwardNextHop)
        {
            DeleteIpForwardEntry( &Adapter->RouterMib );
            Adapter->RouterMib.dwForwardNextHop = 0;
        }
        
        Adapter->DhclientState.state = S_STATIC;
        proto = find_protocol_by_adapter( &Adapter->DhclientInfo );
        if (proto)
            remove_protocol(proto);
        Status = AddIPAddress( Req->Body.StaticRefreshParams.IPAddress,
                               Req->Body.StaticRefreshParams.Netmask,
                               Req->AdapterIndex,
                               &Adapter->NteContext,
                               &Adapter->NteInstance );
        Reply.Reply = NT_SUCCESS(Status);

        if (AdapterStateChangedEvent != NULL)
            SetEvent(AdapterStateChangedEvent);
    }

    ApiUnlock();

    return Send( &Reply );
}
Example #5
0
DWORD DSReleaseIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
    COMM_DHCP_REPLY Reply;
    PDHCP_ADAPTER Adapter;
    struct protocol* proto;

    ApiLock();

    Adapter = AdapterFindIndex( Req->AdapterIndex );

    Reply.Reply = Adapter ? 1 : 0;

    if( Adapter ) {
        if (Adapter->NteContext)
        {
            DeleteIPAddress( Adapter->NteContext );
            Adapter->NteContext = 0;
        }
        if (Adapter->RouterMib.dwForwardNextHop)
        {
            DeleteIpForwardEntry( &Adapter->RouterMib );
            Adapter->RouterMib.dwForwardNextHop = 0;
        }

        proto = find_protocol_by_adapter( &Adapter->DhclientInfo );
        if (proto)
           remove_protocol(proto);

        Adapter->DhclientInfo.client->active = NULL;
        Adapter->DhclientInfo.client->state = S_INIT;

        if (AdapterStateChangedEvent != NULL)
            SetEvent(AdapterStateChangedEvent);
    }

    ApiUnlock();

    return Send( &Reply );
}
Example #6
0
/*
 * XXX Figure out the way to bind a specific adapter to a socket.
 */
DWORD WINAPI AdapterDiscoveryThread(LPVOID Context) {
    PMIB_IFTABLE Table = (PMIB_IFTABLE) malloc(sizeof(MIB_IFTABLE));
    DWORD Error, Size = sizeof(MIB_IFTABLE);
    PDHCP_ADAPTER Adapter = NULL;
    HANDLE AdapterStateChangedEvent = (HANDLE)Context;
    struct interface_info *ifi = NULL;
    struct protocol *proto;
    int i, AdapterCount = 0, Broadcast;

    /* FIXME: Kill this thread when the service is stopped */

    do {
       DH_DbgPrint(MID_TRACE,("Getting Adapter List...\n"));

       while( (Error = GetIfTable(Table, &Size, 0 )) ==
               ERROR_INSUFFICIENT_BUFFER ) {
           DH_DbgPrint(MID_TRACE,("Error %d, New Buffer Size: %d\n", Error, Size));
           free( Table );
           Table = (PMIB_IFTABLE) malloc( Size );
       }

       if( Error != NO_ERROR )
       {
           /* HACK: We are waiting until TCP/IP starts */
           Sleep(2000);
           continue;
       }

       DH_DbgPrint(MID_TRACE,("Got Adapter List (%d entries)\n", Table->dwNumEntries));

       for( i = Table->dwNumEntries - 1; i >= 0; i-- ) {
            DH_DbgPrint(MID_TRACE,("Getting adapter %d attributes\n",
                                   Table->table[i].dwIndex));

            ApiLock();

            if ((Adapter = AdapterFindByHardwareAddress(Table->table[i].bPhysAddr, Table->table[i].dwPhysAddrLen)))
            {
                proto = find_protocol_by_adapter(&Adapter->DhclientInfo);

                /* This is an existing adapter */
                if (InterfaceConnected(&Table->table[i])) {
                    /* We're still active so we stay in the list */
                    ifi = &Adapter->DhclientInfo;

                    /* This is a hack because IP helper API sucks */
                    if (IsReconnectHackNeeded(Adapter, &Table->table[i]))
                    {
                        /* This handles a disconnect/reconnect */

                        if (proto)
                            remove_protocol(proto);
                        Adapter->DhclientInfo.client->state = S_INIT;

                        /* These are already invalid since the media state change */
                        Adapter->RouterMib.dwForwardNextHop = 0;
                        Adapter->NteContext = 0;

                        add_protocol(Adapter->DhclientInfo.name,
                                     Adapter->DhclientInfo.rfdesc,
                                     got_one, &Adapter->DhclientInfo);
                        state_init(&Adapter->DhclientInfo);

                        SetEvent(AdapterStateChangedEvent);
                    }

                } else {
                    if (proto)
                        remove_protocol(proto);

                    /* We've lost our link so out we go */
                    RemoveEntryList(&Adapter->ListEntry);
                    free(Adapter);
                }

                ApiUnlock();

                continue;
            }

            ApiUnlock();

            Adapter = (DHCP_ADAPTER*) calloc( sizeof( DHCP_ADAPTER ) + Table->table[i].dwMtu, 1 );

            if( Adapter && Table->table[i].dwType == MIB_IF_TYPE_ETHERNET && InterfaceConnected(&Table->table[i])) {
                memcpy( &Adapter->IfMib, &Table->table[i],
                        sizeof(Adapter->IfMib) );
                Adapter->DhclientInfo.client = &Adapter->DhclientState;
                Adapter->DhclientInfo.rbuf = Adapter->recv_buf;
                Adapter->DhclientInfo.rbuf_max = Table->table[i].dwMtu;
                Adapter->DhclientInfo.rbuf_len =
                    Adapter->DhclientInfo.rbuf_offset = 0;
                memcpy(Adapter->DhclientInfo.hw_address.haddr,
                       Adapter->IfMib.bPhysAddr,
                       Adapter->IfMib.dwPhysAddrLen);
                Adapter->DhclientInfo.hw_address.hlen = Adapter->IfMib.dwPhysAddrLen;

                /* I'm not sure where else to set this, but
                   some DHCP servers won't take a zero.
                   We checked the hardware type earlier in
                   the if statement. */
                Adapter->DhclientInfo.hw_address.htype = HTYPE_ETHER;

                if( DhcpSocket == INVALID_SOCKET ) {
                    DhcpSocket =
                        Adapter->DhclientInfo.rfdesc =
                        Adapter->DhclientInfo.wfdesc =
                        socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );

                    if (DhcpSocket != INVALID_SOCKET) {
						
						/* Allow broadcast on this socket */
						Broadcast = 1;
						setsockopt(DhcpSocket,
								   SOL_SOCKET,
								   SO_BROADCAST,
								   (const char *)&Broadcast,
								   sizeof(Broadcast));
						
                        Adapter->ListenAddr.sin_family = AF_INET;
                        Adapter->ListenAddr.sin_port = htons(LOCAL_PORT);
                        Adapter->BindStatus =
                             (bind( Adapter->DhclientInfo.rfdesc,
                                    (struct sockaddr *)&Adapter->ListenAddr,
                                    sizeof(Adapter->ListenAddr) ) == 0) ?
                             0 : WSAGetLastError();
                    } else {
                        error("socket() failed: %d\n", WSAGetLastError());
                    }
                } else {
                    Adapter->DhclientInfo.rfdesc =
                        Adapter->DhclientInfo.wfdesc = DhcpSocket;
                }

                Adapter->DhclientConfig.timeout = DHCP_PANIC_TIMEOUT;
                Adapter->DhclientConfig.initial_interval = DHCP_DISCOVER_INTERVAL;
                Adapter->DhclientConfig.retry_interval = DHCP_DISCOVER_INTERVAL;
                Adapter->DhclientConfig.select_interval = 1;
                Adapter->DhclientConfig.reboot_timeout = DHCP_REBOOT_TIMEOUT;
                Adapter->DhclientConfig.backoff_cutoff = DHCP_BACKOFF_MAX;
                Adapter->DhclientState.interval =
                    Adapter->DhclientConfig.retry_interval;

                if( PrepareAdapterForService( Adapter ) ) {
                    Adapter->DhclientInfo.next = ifi;
                    ifi = &Adapter->DhclientInfo;

                    read_client_conf(&Adapter->DhclientInfo);

                    if (Adapter->DhclientInfo.client->state == S_INIT)
                    {
                        add_protocol(Adapter->DhclientInfo.name,
                                     Adapter->DhclientInfo.rfdesc,
                                     got_one, &Adapter->DhclientInfo);

                        state_init(&Adapter->DhclientInfo);
                    }

                    ApiLock();
                    InsertTailList( &AdapterList, &Adapter->ListEntry );
                    AdapterCount++;
                    SetEvent(AdapterStateChangedEvent);
                    ApiUnlock();
                } else { free( Adapter ); Adapter = 0; }
            } else { free( Adapter ); Adapter = 0; }

            if( !Adapter )
                DH_DbgPrint(MID_TRACE,("Adapter %d was rejected\n",
                                       Table->table[i].dwIndex));
        }
#if 0
        Error = NotifyAddrChange(NULL, NULL);
        if (Error != NO_ERROR)
            break;
#else
        Sleep(3000);
#endif
    } while (TRUE);

    DbgPrint("DHCPCSVC: Adapter discovery thread is terminating! (Error: %d)\n", Error);

    if( Table ) free( Table );
    return Error;
}
Example #7
0
static __saveds void net_func(void)
{
	const char *str;
	BYTE od_error;
	struct MsgPort *write_port = NULL, *control_port = NULL;
	struct IOSana2Req *write_io = NULL, *control_io = NULL;
	bool opened = false;
	ULONG read_mask = 0, write_mask = 0, proc_port_mask = 0;
	struct Sana2DeviceQuery query_data = {sizeof(Sana2DeviceQuery)};
	ULONG buffer_tags[] = {
		S2_CopyToBuff, (uint32)copy_to_buff,
		S2_CopyFromBuff, (uint32)copy_from_buff,
		TAG_END
	};

	// Default: error occured
	proc_error = true;

	// Create message port for communication with main task
	proc_port = CreateMsgPort();
	if (proc_port == NULL)
		goto quit;
	proc_port_mask = 1 << proc_port->mp_SigBit;

	// Create message ports for device I/O
	read_port = CreateMsgPort();
	if (read_port == NULL)
		goto quit;
	read_mask = 1 << read_port->mp_SigBit;
	write_port = CreateMsgPort();
	if (write_port == NULL)
		goto quit;
	write_mask = 1 << write_port->mp_SigBit;
	control_port = CreateMsgPort();
	if (control_port == NULL)
		goto quit;

	// Create control IORequest
	control_io = (struct IOSana2Req *)CreateIORequest(control_port, sizeof(struct IOSana2Req));
	if (control_io == NULL)
		goto quit;
	control_io->ios2_Req.io_Message.mn_Node.ln_Type = 0;	// Avoid CheckIO() bug

	// Parse device name
	char dev_name[256];
	ULONG dev_unit;

	str = PrefsFindString("ether");
	if (str) {
		const char *FirstSlash = strchr(str, '/');
		const char *LastSlash = strrchr(str, '/');

		if (FirstSlash && FirstSlash && FirstSlash != LastSlash) {

			// Device name contains path, i.e. "Networks/xyzzy.device"
			const char *lp = str;
			char *dp = dev_name;

			while (lp != LastSlash)
				*dp++ = *lp++;
			*dp = '\0';

			if (strlen(dev_name) < 1)
				goto quit;

			if (sscanf(LastSlash, "/%ld", &dev_unit) != 1)
				goto quit;
		} else {
			if (sscanf(str, "%[^/]/%ld", dev_name, &dev_unit) != 2)
				goto quit;
		}
	} else
		goto quit;

	// Open device
	control_io->ios2_BufferManagement = buffer_tags;
	od_error = OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)control_io, 0);
	if (od_error != 0 || control_io->ios2_Req.io_Device == 0) {
		printf("WARNING: OpenDevice(<%s>, unit=%d) returned error %d)\n", (UBYTE *)dev_name, dev_unit, od_error);
		goto quit;
	}
	opened = true;

	// Is it Ethernet?
	control_io->ios2_Req.io_Command = S2_DEVICEQUERY;
	control_io->ios2_StatData = (void *)&query_data;
	DoIO((struct IORequest *)control_io);
	if (control_io->ios2_Req.io_Error)
		goto quit;
	if (query_data.HardwareType != S2WireType_Ethernet) {
		WarningAlert(GetString(STR_NOT_ETHERNET_WARN));
		goto quit;
	}

	// Yes, create IORequest for writing
	write_io = (struct IOSana2Req *)CreateIORequest(write_port, sizeof(struct IOSana2Req));
	if (write_io == NULL)
		goto quit;
	memcpy(write_io, control_io, sizeof(struct IOSana2Req));
	write_io->ios2_Req.io_Message.mn_Node.ln_Type = 0;	// Avoid CheckIO() bug
	write_io->ios2_Req.io_Message.mn_ReplyPort = write_port;

	// Configure Ethernet
	control_io->ios2_Req.io_Command = S2_GETSTATIONADDRESS;
	DoIO((struct IORequest *)control_io);
	memcpy(ether_addr, control_io->ios2_DstAddr, 6);
	memcpy(control_io->ios2_SrcAddr, control_io->ios2_DstAddr, 6);
	control_io->ios2_Req.io_Command = S2_CONFIGINTERFACE;
	DoIO((struct IORequest *)control_io);
	D(bug("Ethernet address %08lx %08lx\n", *(uint32 *)ether_addr, *(uint16 *)(ether_addr + 4)));

	// Initialization went well, inform main task
	proc_error = false;
	Signal(MainTask, SIGF_SINGLE);

	// Main loop
	for (;;) {

		// Wait for I/O and messages (CTRL_C is used for quitting the task)
		ULONG sig = Wait(proc_port_mask | read_mask | write_mask | SIGBREAKF_CTRL_C);

		// Main task wants to quit us
		if (sig & SIGBREAKF_CTRL_C)
			break;

		// Main task sent a command to us
		if (sig & proc_port_mask) {
			struct NetMessage *msg;
			while (msg = (NetMessage *)GetMsg(proc_port)) {
				D(bug("net_proc received %08lx\n", msg->what));
				switch (msg->what) {
					case MSG_CLEANUP:
						remove_all_protocols();
						break;

					case MSG_ADD_MULTI:
						control_io->ios2_Req.io_Command = S2_ADDMULTICASTADDRESS;
						Mac2Host_memcpy(control_io->ios2_SrcAddr, msg->pointer + eMultiAddr, 6);
						DoIO((struct IORequest *)control_io);
						if (control_io->ios2_Req.io_Error == S2ERR_NOT_SUPPORTED) {
							WarningAlert(GetString(STR_NO_MULTICAST_WARN));
							msg->result = noErr;
						} else if (control_io->ios2_Req.io_Error)
							msg->result = eMultiErr;
						else
							msg->result = noErr;
						break;

					case MSG_DEL_MULTI:
						control_io->ios2_Req.io_Command = S2_DELMULTICASTADDRESS;
						Mac2Host_memcpy(control_io->ios2_SrcAddr, msg->pointer + eMultiAddr, 6);
						DoIO((struct IORequest *)control_io);
						if (control_io->ios2_Req.io_Error)
							msg->result = eMultiErr;
						else
							msg->result = noErr;
						break;

					case MSG_ATTACH_PH: {
						uint16 type = msg->type;
						uint32 handler = msg->pointer;

						// Protocol of that type already installed?
						NetProtocol *p = (NetProtocol *)prot_list.lh_Head, *next;
						while ((next = (NetProtocol *)p->ln_Succ) != NULL) {
							if (p->type == type) {
								msg->result = lapProtErr;
								goto reply;
							}
							p = next;
						}

						// Allocate NetProtocol, set type and handler
						p = (NetProtocol *)AllocMem(sizeof(NetProtocol), MEMF_PUBLIC);
						if (p == NULL) {
							msg->result = lapProtErr;
							goto reply;
						}
						p->type = type;
						p->handler = handler;

						// Set up and submit read requests
						for (int i=0; i<NUM_READ_REQUESTS; i++) {
							memcpy(p->read_io + i, control_io, sizeof(struct IOSana2Req));
							p->read_io[i].ios2_Req.io_Message.mn_Node.ln_Name = (char *)p;	// Hide pointer to NetProtocol in node name
							p->read_io[i].ios2_Req.io_Message.mn_Node.ln_Type = 0;			// Avoid CheckIO() bug
							p->read_io[i].ios2_Req.io_Message.mn_ReplyPort = read_port;
							p->read_io[i].ios2_Req.io_Command = CMD_READ;
							p->read_io[i].ios2_PacketType = type;
							p->read_io[i].ios2_Data = p->read_buf[i];
							p->read_io[i].ios2_Req.io_Flags = SANA2IOF_RAW;
							BeginIO((struct IORequest *)(p->read_io + i));
						}

						// Add protocol to list
						AddTail(&prot_list, p);

						// Everything OK
						msg->result = noErr;
						break;
					}

					case MSG_DETACH_PH: {
						uint16 type = msg->type;
						msg->result = lapProtErr;
						NetProtocol *p = (NetProtocol *)prot_list.lh_Head, *next;
						while ((next = (NetProtocol *)p->ln_Succ) != NULL) {
							if (p->type == type) {
								remove_protocol(p);
								msg->result = noErr;
								break;
							}
							p = next;
						}
						break;
					}

					case MSG_WRITE: {
						// Get pointer to Write Data Structure
						uint32 wds = msg->pointer;
						write_io->ios2_Data = (void *)wds;

						// Calculate total packet length
						long len = 0;
						uint32 tmp = wds;
						for (;;) {
							int16 w = ReadMacInt16(tmp);
							if (w == 0)
								break;
							len += w;
							tmp += 6;
						}
						write_io->ios2_DataLength = len;

						// Get destination address
						uint32 hdr = ReadMacInt32(wds + 2);
						Mac2Host_memcpy(write_io->ios2_DstAddr, hdr, 6);

						// Get packet type
						uint32 type = ReadMacInt16(hdr + 12);
						if (type <= 1500)
							type = 0;		// 802.3 packet
						write_io->ios2_PacketType = type;

						// Multicast/broadcard packet?
						if (write_io->ios2_DstAddr[0] & 1) {
							if (*(uint32 *)(write_io->ios2_DstAddr) == 0xffffffff && *(uint16 *)(write_io->ios2_DstAddr + 4) == 0xffff)
								write_io->ios2_Req.io_Command = S2_BROADCAST;
							else
								write_io->ios2_Req.io_Command = S2_MULTICAST;
						} else
							write_io->ios2_Req.io_Command = CMD_WRITE;

						// Send packet
						write_done = false;
						write_io->ios2_Req.io_Flags = SANA2IOF_RAW;
						BeginIO((IORequest *)write_io);
						break;
					}
				}
reply:			D(bug(" net_proc replying\n"));
				ReplyMsg(msg);
			}
		}

		// Packet received
		if (sig & read_mask) {
			D(bug(" packet received, triggering Ethernet interrupt\n"));
			SetInterruptFlag(INTFLAG_ETHER);
			TriggerInterrupt();
		}

		// Packet write completed
		if (sig & write_mask) {
			GetMsg(write_port);
			WriteMacInt32(ether_data + ed_Result, write_io->ios2_Req.io_Error ? excessCollsns : 0);
			write_done = true;
			D(bug(" packet write done, triggering Ethernet interrupt\n"));
			SetInterruptFlag(INTFLAG_ETHER);
			TriggerInterrupt();
		}
	}
quit:

	// Close everything
	remove_all_protocols();
	if (opened) {
		if (CheckIO((struct IORequest *)write_io) == 0) {
			AbortIO((struct IORequest *)write_io);
			WaitIO((struct IORequest *)write_io);
		}
		CloseDevice((struct IORequest *)control_io);
	}
	if (write_io)
		DeleteIORequest(write_io);
	if (control_io)
		DeleteIORequest(control_io);
	if (control_port)
		DeleteMsgPort(control_port);
	if (write_port)
		DeleteMsgPort(write_port);
	if (read_port)
		DeleteMsgPort(read_port);

	// Send signal to main task to confirm termination
	Forbid();
	Signal(MainTask, SIGF_SINGLE);
}