blob: 6b7cee6db87a3d92f509c8832094f35ff7a66872 [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
Ray Milkey269ffb92014-04-03 14:43:30 -07002 * Copyright 2011, Big Switch Networks, Inc.
3 * Originally created by David Erickson, Stanford University
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 * not use this file except in compliance with the License. You may obtain
7 * a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations
15 * under the License.
16 **/
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080017
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070018package net.onrc.onos.core.packet;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080019
20import java.nio.ByteBuffer;
21import java.util.HashMap;
22import java.util.Map;
23
24/**
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080025 * @author David Erickson (daviderickson@cs.stanford.edu)
26 */
27public class UDP extends BasePacket {
28 public static Map<Short, Class<? extends IPacket>> decodeMap;
Ray Milkey269ffb92014-04-03 14:43:30 -070029 public static short DHCP_SERVER_PORT = (short) 67;
30 public static short DHCP_CLIENT_PORT = (short) 68;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080031
32 static {
33 decodeMap = new HashMap<Short, Class<? extends IPacket>>();
34 /*
35 * Disable DHCP until the deserialize code is hardened to deal with garbage input
36 */
37 UDP.decodeMap.put(DHCP_SERVER_PORT, DHCP.class);
38 UDP.decodeMap.put(DHCP_CLIENT_PORT, DHCP.class);
Ray Milkey269ffb92014-04-03 14:43:30 -070039
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080040 }
41
42 protected short sourcePort;
43 protected short destinationPort;
44 protected short length;
45 protected short checksum;
46
47 /**
48 * @return the sourcePort
49 */
50 public short getSourcePort() {
51 return sourcePort;
52 }
53
54 /**
55 * @param sourcePort the sourcePort to set
56 */
57 public UDP setSourcePort(short sourcePort) {
58 this.sourcePort = sourcePort;
59 return this;
60 }
61
62 /**
63 * @return the destinationPort
64 */
65 public short getDestinationPort() {
66 return destinationPort;
67 }
68
69 /**
70 * @param destinationPort the destinationPort to set
71 */
72 public UDP setDestinationPort(short destinationPort) {
73 this.destinationPort = destinationPort;
74 return this;
75 }
76
77 /**
78 * @return the length
79 */
80 public short getLength() {
81 return length;
82 }
83
84 /**
85 * @return the checksum
86 */
87 public short getChecksum() {
88 return checksum;
89 }
90
91 /**
92 * @param checksum the checksum to set
93 */
94 public UDP setChecksum(short checksum) {
95 this.checksum = checksum;
96 return this;
97 }
98
99 @Override
100 public void resetChecksum() {
101 this.checksum = 0;
102 super.resetChecksum();
103 }
104
105 /**
106 * Serializes the packet. Will compute and set the following fields if they
107 * are set to specific values at the time serialize is called:
Ray Milkey269ffb92014-04-03 14:43:30 -0700108 * -checksum : 0
109 * -length : 0
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800110 */
111 public byte[] serialize() {
112 byte[] payloadData = null;
113 if (payload != null) {
114 payload.setParent(this);
115 payloadData = payload.serialize();
116 }
117
118 this.length = (short) (8 + ((payloadData == null) ? 0
119 : payloadData.length));
120
121 byte[] data = new byte[this.length];
122 ByteBuffer bb = ByteBuffer.wrap(data);
123
124 bb.putShort(this.sourcePort);
125 bb.putShort(this.destinationPort);
126 bb.putShort(this.length);
127 bb.putShort(this.checksum);
128 if (payloadData != null)
129 bb.put(payloadData);
130
131 if (this.parent != null && this.parent instanceof IPv4)
Ray Milkey269ffb92014-04-03 14:43:30 -0700132 ((IPv4) this.parent).setProtocol(IPv4.PROTOCOL_UDP);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800133
134 // compute checksum if needed
135 if (this.checksum == 0) {
136 bb.rewind();
137 int accumulation = 0;
138
139 // compute pseudo header mac
140 if (this.parent != null && this.parent instanceof IPv4) {
141 IPv4 ipv4 = (IPv4) this.parent;
142 accumulation += ((ipv4.getSourceAddress() >> 16) & 0xffff)
143 + (ipv4.getSourceAddress() & 0xffff);
144 accumulation += ((ipv4.getDestinationAddress() >> 16) & 0xffff)
145 + (ipv4.getDestinationAddress() & 0xffff);
146 accumulation += ipv4.getProtocol() & 0xff;
147 accumulation += this.length & 0xffff;
148 }
149
150 for (int i = 0; i < this.length / 2; ++i) {
151 accumulation += 0xffff & bb.getShort();
152 }
153 // pad to an even number of shorts
154 if (this.length % 2 > 0) {
155 accumulation += (bb.get() & 0xff) << 8;
156 }
157
158 accumulation = ((accumulation >> 16) & 0xffff)
159 + (accumulation & 0xffff);
160 this.checksum = (short) (~accumulation & 0xffff);
161 bb.putShort(6, this.checksum);
162 }
163 return data;
164 }
165
166 /* (non-Javadoc)
167 * @see java.lang.Object#hashCode()
168 */
169 @Override
170 public int hashCode() {
171 final int prime = 5807;
172 int result = super.hashCode();
173 result = prime * result + checksum;
174 result = prime * result + destinationPort;
175 result = prime * result + length;
176 result = prime * result + sourcePort;
177 return result;
178 }
179
180 /* (non-Javadoc)
181 * @see java.lang.Object#equals(java.lang.Object)
182 */
183 @Override
184 public boolean equals(Object obj) {
185 if (this == obj)
186 return true;
187 if (!super.equals(obj))
188 return false;
189 if (!(obj instanceof UDP))
190 return false;
191 UDP other = (UDP) obj;
192 if (checksum != other.checksum)
193 return false;
194 if (destinationPort != other.destinationPort)
195 return false;
196 if (length != other.length)
197 return false;
198 if (sourcePort != other.sourcePort)
199 return false;
200 return true;
201 }
202
203 @Override
204 public IPacket deserialize(byte[] data, int offset, int length) {
205 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
206 this.sourcePort = bb.getShort();
207 this.destinationPort = bb.getShort();
208 this.length = bb.getShort();
209 this.checksum = bb.getShort();
210
211 if (UDP.decodeMap.containsKey(this.destinationPort)) {
212 try {
213 this.payload = UDP.decodeMap.get(this.destinationPort).getConstructor().newInstance();
214 } catch (Exception e) {
215 throw new RuntimeException("Failure instantiating class", e);
216 }
217 } else if (UDP.decodeMap.containsKey(this.sourcePort)) {
218 try {
219 this.payload = UDP.decodeMap.get(this.sourcePort).getConstructor().newInstance();
220 } catch (Exception e) {
221 throw new RuntimeException("Failure instantiating class", e);
222 }
223 } else {
224 this.payload = new Data();
225 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700226 this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800227 this.payload.setParent(this);
228 return this;
229 }
230}