/* * Copyright (c) Martin Schoeberl, martin@jopdesign.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Martin Schoeberl * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ package ejip_old; /* * Changelog: * 2002-10-24 creation. * * TODO: in Udp, TcpIp.... when to use the packet with automatic reply? */ import util.Dbg; /** * @author martin * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ /** * UDP functions. */ public class Udp { public static final int PROTOCOL = 17; public static final int HEAD = 5; // offset of udp header in words public static final int DATA = 7; // offset of data in words private static Object monitor; public static final int MAX_HANDLER = 8; private static UdpHandler[] list; private static int[] ports; private static int loopCnt; public static void init() { if (monitor!=null) return; monitor = new Object(); list = new UdpHandler[MAX_HANDLER]; ports = new int[MAX_HANDLER]; loopCnt = 0; addHandler(Tftp.PORT, new Tftp()); } /** * add a handler for UDP requests. * returns false if list is full. */ public static boolean addHandler(int port, UdpHandler h) { if (monitor==null) init(); synchronized(monitor) { for (int i=0; i<MAX_HANDLER; ++i) { if (list[i]==null) { ports[i] = port; list[i] = h; return true; } } } return false; } /** * remove a handler for UDP requests. * returns false if it was not in the list. */ public static boolean removeHandler(int port) { if (monitor==null) init(); synchronized(monitor) { for (int i=0; i<MAX_HANDLER; ++i) { if (list[i]!=null) { if (ports[i] == port) { list[i] = null; return true; } } } } return false; } /** * Called periodic from Net for timeout processing. */ static void loop() { int i = loopCnt; if (list[i]!=null) { list[i].loop(); ++i; if (i==MAX_HANDLER) i=0; } else { i = 0; } loopCnt = i; } /** * process packet and generate reply if necessary. */ static void process(Packet p) { int i, j; int[] buf = p.buf; int port = buf[HEAD]; int remport = port >>> 16; port &= 0xffff; buf[2] = (PROTOCOL<<16) + p.len - 20; // set protocol and udp length in iph checksum for tcp checksum if (Ip.chkSum(buf, 2, p.len-8)!=0) { Dbg.intVal(p.len); Dbg.wr(" : "); for (int k = 0; k < (p.len+3)/4; k++) { Dbg.hexVal(buf[k]); } p.setStatus(Packet.FREE); // mark packet free Dbg.wr("wrong UDP checksum "); return; } if (port == 1625) { // do the Dgb thing! i = Dbg.readBuffer(buf, 7); p.len = 28+i; // generate a reply with IP src/dst exchanged Udp.build(p, buf[4], buf[3], remport); } else { if (list!=null) { for (i=0; i<MAX_HANDLER; ++i) { if (list[i]!=null && ports[i]==port) { list[i].request(p); break; } } if (i==MAX_HANDLER) { p.setStatus(Packet.FREE); // mark packet free Dbg.lf(); Dbg.wr('U'); Dbg.intVal(port); } } else { p.setStatus(Packet.FREE); } } } /** * Generate a reply with IP src/dst exchanged. * @param p */ public static void reply(Packet p) { int[] buf = p.buf; Udp.build(p, buf[4], buf[3], buf[HEAD]>>>16); } /** * Get source IP from interface and build IP/UDP header. */ public static void build(Packet p, int dstIp, int port) { int srcIp = p.interf.getIpAddress(); if (srcIp==0) { // interface is down p.setStatus(Packet.FREE); // mark packet free } else { build(p, srcIp, dstIp, port); } } /** * Fill UDP and IP header and mark packet ready to send. */ public static void build(Packet p, int srcIp, int dstIp, int port) { int i; int[] buf = p.buf; // IP header // TODO unique id for sent packet buf[0] = 0x45000000 + p.len; // ip length (header without options) buf[1] = Ip.getId(); // identification, no fragmentation buf[3] = srcIp; buf[4] = dstIp; // UDP header // 'set' port numbers buf[HEAD] = ((port+10000)<<16) + port; // src port = dst port + 10000 // Fill in UDP header buf[HEAD+1] = (p.len-20)<<16; buf[2] = (PROTOCOL<<16) + p.len - 20; // set protocol and udp length in iph checksum for tcp checksum i = Ip.chkSum(buf, 2, p.len-8); if (i==0) i = 0xffff; buf[HEAD+1] |= i; // for UDP checksum used field of IP header buf[2] = (0x20<<24) + (PROTOCOL<<16); // ttl, protocol, clear checksum buf[2] |= Ip.chkSum(buf, 0, 20); p.llh[6] = 0x0800; p.setStatus(Packet.SND_DGRAM); // mark packet ready to send } }