! UDP module for (Moose) INet process, GDMR, Feb/March 1987, Jan 1988. ! TX checksums now turned on ({C}/!C!) !%option "-NonStandard-NoCheck-Nodiag-NoLine" %option "-NonStandard-NoCheck" %include "INet:Control.Inc" %externalintegerspec control %include "INet:Formats.Inc" %include "INet:Utility.Inc" %include "INet:INet.Inc" %include "INet:Stats.Inc" %externalroutinespec IP outbound(%record(buffer fm)%name b) %externalroutinespec UDP send to user(%record(buffer fm)%name b) %externalroutinespec UDP open response(%integer unit, error, ra, rp, lp) %externalroutinespec UDP claim response(%integer unit, error, allocated) %externalroutinespec UDP enable(%integer unit) %externalroutinespec UDP disable(%integer unit, error) %externalpredicatespec UDP interpret user request(%record(buffer fm)%name b) %externalintegerfnspec IP source for(%integer d) %externalintegerspec max UDP %systemroutinespec phex(%integer x) %externalrecord(INet statistics fm)%spec stats %externalrecord(UDP table fm)%namespec UDP table %constinteger wild UDP port flag = 16_00010000 %constinteger UDP port mask = 16_0000FFFF %constinteger UDP privileged limit = 1024 %record(UDP entry fm)%map find UDP entry(%integer remote address, remote port, %integer local port) ! Try for an exact match if possible. If not, try for a wild match. %record(UDP entry fm)%name t, possible == nil %integer i %for i = 1, 1, max UDP %cycle t == UDP table_UDP(i) !! printstring("Trying "); print inet address(t_remote address) !! write(t_remote port, 1); write(t_local port, 1); newline %if t_local port = local port %start %result == t %if t_remote address = remote address %c %and (t_remote port = remote port %c %or t_remote port & wild UDP port flag # 0) possible == t %if t_remote address = 0 %finish %repeat %result == possible %end %externalroutine UDP inbound(%record(buffer fm)%name b) %integer c, host, net, class !L! lights or A(UDP light) %if b_UDP header_checksum = 0 %start !! printstring("No UDP checksum"); newline stats_UDP no checksums = stats_UDP no checksums + 1 %else c = calculate pseudo checksum(b_UDP header, b_IP bytes, b_IP header_source, b_IP header_destination, IP UDP protocol, b_IP bytes) %if 0 # c # 16_FFFF %start !! printstring("UDP checksum error "); phex(c); newline c = calculate pseudo checksum(b_UDP header, b_IP bytes, b_IP header_source, b_IP header_destination, IP UDP protocol, b_UDP header_length) %if c = 0 %or c = 16_FFFF %start !! printstring("Bogus UDP checksum "); phex(c); newline stats_UDP bogus checksums = stats_UDP bogus checksums + 1 %else !! printstring("UDP checksum error "); phex(c); newline stats_UDP checksum errors = stats_UDP checksum errors + 1 %finish %finish %finish !N! net order short(b_UDP header_source) !N! net order short(b_UDP header_destination) !N! net order short(b_UDP header_length) !N! net order short(b_UDP header_checksum) %if b_UDP header_length # b_IP bytes %start ! Length wrong pdate printstring("UDP length error from ") print inet address(b_IP header_source) printstring(": UDP length "); write(b_UDP header_length, 0) printstring(", IP length "); write(b_IP bytes, 0); newline stats_UDP other errors = stats_UDP other errors + 1 release buffer(b) -> out %finish b_data start == byteinteger(addr(b_UDP header) + 8) b_data bytes = b_UDP header_length - 8 stats_UDP packets in = stats_UDP packets in + 1 stats_UDP bytes in = stats_UDP bytes in + b_data bytes %if control & trace UDP in # 0 %start printstring("UDP inbound from ") print inet address(b_IP header_source) printstring(" port "); write(b_UDP header_source, 0) printstring(" for port "); write(b_UDP header_destination, 0) printstring(", data size "); write(b_data bytes, 0) newline dump(b_data start, b_data bytes) %finish b_UDP entry == find UDP entry(b_IP peer, b_UDP header_source, b_UDP header_destination) %if b_UDP entry == nil %start ! No-one there to receive it %if control & trace orphan UDP # 0 %start printstring("UDP ") printstring("broadcast ") %if b_flags & broadcast flag # 0 print INet address(b_IP header_source) print symbol('.'); write(b_UDP header_source, 0) print symbol('/'); write(b_UDP header_destination, 0) printstring(" dropped -- no recipient") newline dump(b_data start, b_data bytes) %finish release buffer(b) %else ! Send it to the port's owner !! printstring("Sending UDP to "); write(b_UDP entry_slot, 0); newline %if b_UDP entry_remote address = 0 %start ! Wild context. Should we convert it? split INet address(b_IP header_destination, host, net, class) %if 0 # host # new broadcast mask(class) %start ! Not a broadcast b_UDP entry_remote address = b_IP peer b_UDP entry_remote port = b_UDP header_source !! printstring("Wild UDP context converted to ") !! print inet address(b_IP peer); print symbol('.') !! write(b_UDP header_source, 0); newline %finish %else %if b_UDP entry_remote port & wild UDP port flag # 0 b_UDP entry_remote port = b_UDP header_source !! printstring("Wild remote port converted to ") !! write(b_UDP entry_remote port, 0); newline %finish UDP send to user(b) %finish out: !L! lights and A(\UDP light) %end %externalroutine UDP outbound(%record(buffer fm)%name b) %owninteger UDP last privileged = UDP privileged limit %owninteger UDP last unprivileged = UDP privileged limit %switch op(UDP first request : UDP last request) %recordformat connect fm(%integer remote address, remote port, local port) %record(connect fm)%name connect %integer i, which, c !L! lights or B(UDP light) !! printstring("UDP outbound"); newline -> op(b_code) %if UDP interpret user request(b) !! printstring("Dud request from "); write(b_UDP entry_slot, 0); newline release buffer(b) -> out op(UDP define context request): connect == record(addr(b_data start)) !! printstring("Define context from "); write(b_UDP entry_slot, 0) !! printstring(": "); print INet address(connect_remote address) !! space; write(connect_remote port & UDP port mask, 0) !! space; write(connect_local port, 0) !! printstring(", flags "); phex(connect_remote port & 16_FFFF0000) !! newline %if b_privilege = 0 %and %c (connect_local port <= UDP privileged limit %or %c connect_remote address = 0) %start UDP open response(b_UDP entry_slot, privilege error, 0, 0, 0) release buffer(b) -> out %finish b_UDP entry_remote address = connect_remote address b_UDP entry_remote port = connect_remote port b_UDP entry_local port = connect_local port op(UDP query context request): !! printstring("Responding with defined context"); newline UDP open response(b_UDP entry_slot, 0, b_UDP entry_remote address, b_UDP entry_remote port, b_UDP entry_local port) release buffer(b) -> out op(UDP forget context request): UDP disable(b_UDP entry_slot, 0) UDP enable(b_UDP entry_slot) b_UDP entry = 0 release buffer(b) -> out op(UDP data request): !! printstring("Send to "); print INet address(b_UDP entry_remote address) !! space; write(b_UDP entry_remote port & UDP port mask, 0) !! space; write(b_UDP entry_local port, 0); newline %if b_UDP entry_local port = 0 %or b_UDP entry_remote port = 0 %start ! Undefined address -- dump it silently ! (it's an unreliable protocol anyway!) release buffer(b) -> out %finish b_IP peer = b_UDP entry_remote address b_IP peer = -1 %if b_IP peer = 0; ! Broadcast <<<<<<<< b_IP bytes = b_data bytes + 8 b_protocol = IP UDP protocol b_UDP header == record(addr(b_data start) - 8) b_UDP header_source = b_UDP entry_local port b_UDP header_destination = b_UDP entry_remote port & UDP port mask b_UDP header_length = b_IP bytes b_UDP header_checksum = 0; ! Initially !! dump(byteinteger(addr(b_UDP header)), b_IP bytes) !N! net order short(b_UDP header_source) !N! net order short(b_UDP header_destination) !N! net order short(b_UDP header_length) {C} c = calculate pseudo checksum(b_UDP header, b_IP bytes, {C} IP source for(b_IP peer), b_IP peer, {C} IP UDP protocol, b_IP bytes) {C} b_UDP header_checksum <- \c {C} b_UDP header_checksum <- 16_FFFF %if b_UDP header_checksum = 0 IP outbound(b) -> out op(UDP claim request): op(UDP claim priv request): !! printstring("Claim port request from ") !! write(b_UDP entry_slot, 0); newline try claim port again: %if b_code = UDP claim priv request %start %if b_privilege = 0 %start UDP claim response(b_UDP entry_slot, privilege error, 0) release buffer(b) -> out %finish UDP last privileged = UDP last privileged - 1 UDP last privileged = 1023 %if UDP last privileged < 768 which = UDP last privileged !! printstring("Looking for privileged, trying ") !! write(which, 0); newline %else UDP last unprivileged = UDP last unprivileged + 1 UDP last unprivileged = 1025 %if UDP last unprivileged > 2048 which = UDP last unprivileged !! printstring("Looking for unprivileged, trying ") !! write(which, 0); newline %finish %for i = 1, 1, max UDP %cycle -> try claim port again %if UDP table_UDP(i)_local port = which %repeat ! If we fall through here then the port was free... !! printstring("Allocated "); write(which, 0); newline UDP claim response(b_UDP entry_slot, 0, which) release buffer(b) out: !L! lights and B(\UDP light) %end %end %of %file