1 /** @file
2 WCCP Message parsing and generation.
3
4 @section license License
5
6 Licensed to the Apache Software Foundation (ASF) under one
7 or more contributor license agreements. See the NOTICE file
8 distributed with this work for additional information
9 regarding copyright ownership. The ASF licenses this file
10 to you under the Apache License, Version 2.0 (the
11 "License"); you may not use this file except in compliance
12 with the License. You may obtain a copy of the License at
13
14 http://www.apache.org/licenses/LICENSE-2.0
15
16 Unless required by applicable law or agreed to in writing, software
17 distributed under the License is distributed on an "AS IS" BASIS,
18 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 See the License for the specific language governing permissions and
20 limitations under the License.
21 */
22
23 #include "WccpLocal.h"
24 #include <errno.h>
25 #include <openssl/md5.h>
26 #include "ts/TsException.h"
27 #include "tscore/ink_memory.h"
28 #include "tscore/ink_string.h"
29
30 namespace wccp
31 {
32 // ------------------------------------------------------
33 // ------------------------------------------------------
34 ServiceGroup &
setSvcType(ServiceGroup::Type t)35 ServiceGroup::setSvcType(ServiceGroup::Type t)
36 {
37 if (STANDARD == t) {
38 // For standard service, everything past ID must be zero.
39 memset(&m_priority, 0, sizeof(*this) - (reinterpret_cast<char *>(&m_priority) - reinterpret_cast<char *>(this)));
40 }
41 m_svc_type = t; // store actual type.
42 return *this;
43 }
44
45 bool
operator ==(self const & that) const46 ServiceGroup::operator==(self const &that) const
47 {
48 if (m_svc_type == STANDARD) {
49 // If type are different, fail, else if both are STANDARD
50 // then we need only match on the ID.
51 return that.m_svc_type == STANDARD && m_svc_id == that.m_svc_id;
52 } else if (that.m_svc_type != DYNAMIC) {
53 return false;
54 } else {
55 // Both services are DYNAMIC, check the properties.
56 // Port check is technically too strict -- should ignore
57 // ports beyond the terminating null port. Oh well.
58 return m_svc_id == that.m_svc_id && m_protocol == that.m_protocol && m_flags == that.m_flags && m_priority == that.m_priority &&
59 0 == memcmp(m_ports, that.m_ports, sizeof(m_ports));
60 }
61 }
62 // ------------------------------------------------------
63 // ------------------------------------------------------
64 CacheHashIdElt &
setBucket(int idx,bool state)65 CacheHashIdElt::setBucket(int idx, bool state)
66 {
67 uint8_t &bucket = m_buckets[idx >> 3];
68 uint8_t mask = 1 << (idx & 7);
69 if (state)
70 bucket |= mask;
71 else
72 bucket &= !mask;
73 return *this;
74 }
75
76 CacheHashIdElt &
setBuckets(bool state)77 CacheHashIdElt::setBuckets(bool state)
78 {
79 memset(m_buckets, state ? 0xFF : 0, sizeof(m_buckets));
80 return *this;
81 }
82
83 size_t
getSize() const84 CacheIdBox::getSize() const
85 {
86 return m_size;
87 }
88
89 CacheIdBox &
require(size_t n)90 CacheIdBox::require(size_t n)
91 {
92 if (m_cap < n) {
93 if (m_base && m_cap)
94 ats_free(m_base);
95 m_base = static_cast<CacheIdElt *>(ats_malloc(n));
96 m_cap = n;
97 }
98 memset(m_base, 0, m_cap);
99 m_size = 0;
100 return *this;
101 }
102
103 CacheIdBox &
initDefaultHash(uint32_t addr)104 CacheIdBox::initDefaultHash(uint32_t addr)
105 {
106 this->require(sizeof(CacheHashIdElt));
107 m_size = sizeof(CacheHashIdElt);
108 m_base->initHashRev().setUnassigned(true).setMask(false).setAddr(addr);
109 m_tail = static_cast<CacheHashIdElt *>(m_base)->getTailPtr();
110 m_tail->m_weight = htons(0);
111 m_tail->m_status = htons(0);
112 return *this;
113 }
114
115 CacheIdBox &
initDefaultMask(uint32_t addr)116 CacheIdBox::initDefaultMask(uint32_t addr)
117 {
118 // Base element plus set with 1 value plus tail.
119 this->require(sizeof(CacheMaskIdElt) + MaskValueSetElt::calcSize(1) + sizeof(CacheIdElt::Tail));
120 CacheMaskIdElt *mid = static_cast<CacheMaskIdElt *>(m_base);
121 mid->initHashRev().setUnassigned(true).setMask(true).setAddr(addr);
122 mid->m_assign.init(0, 0, 0, 0)->addValue(addr, 0, 0, 0, 0);
123 m_size = mid->getSize();
124 m_tail = mid->getTailPtr();
125 m_tail->m_weight = htons(0);
126 m_tail->m_status = htons(0);
127 return *this;
128 }
129
130 CacheIdBox &
fill(self const & src)131 CacheIdBox::fill(self const &src)
132 {
133 size_t n = src.getSize();
134 this->require(src.getSize());
135 memcpy(m_base, src.m_base, n);
136 m_size = src.m_size;
137 // If tail is set in src, use the same offset here.
138 if (src.m_tail)
139 m_tail = reinterpret_cast<CacheIdElt::Tail *>(reinterpret_cast<char *>(m_base) +
140 (reinterpret_cast<char *>(src.m_tail) - reinterpret_cast<char *>(src.m_base)));
141 else
142 m_tail = 0;
143 return *this;
144 }
145
146 CacheIdBox &
fill(void * base,self const & src)147 CacheIdBox::fill(void *base, self const &src)
148 {
149 m_size = src.getSize();
150 m_cap = 0;
151 m_base = static_cast<CacheIdElt *>(base);
152 memcpy(m_base, src.m_base, m_size);
153 return *this;
154 }
155
156 int
parse(MsgBuffer base)157 CacheIdBox::parse(MsgBuffer base)
158 {
159 int zret = PARSE_SUCCESS;
160 CacheIdElt *ptr = reinterpret_cast<CacheIdElt *>(base.getTail());
161 size_t n = base.getSpace();
162 m_cap = 0;
163 if (ptr->isMask()) {
164 CacheMaskIdElt *mptr = static_cast<CacheMaskIdElt *>(ptr);
165 size_t size = sizeof(CacheMaskIdElt);
166 // Sanity check - verify enough room for empty elements.
167 if (n < size || n < size + MaskValueSetElt::calcSize(0) * mptr->getCount()) {
168 zret = PARSE_BUFFER_TOO_SMALL;
169 } else {
170 m_size = mptr->getSize();
171 if (n < m_size) {
172 zret = PARSE_BUFFER_TOO_SMALL;
173 logf(LVL_DEBUG, "I_SEE_YOU Cache Mask ID too small: %lu < %lu", n, m_size);
174 } else {
175 m_tail = mptr->getTailPtr();
176 }
177 }
178 } else {
179 if (n < sizeof(CacheHashIdElt)) {
180 zret = PARSE_BUFFER_TOO_SMALL;
181 logf(LVL_DEBUG, "I_SEE_YOU Cache Hash ID too small: %lu < %lu", n, sizeof(CacheHashIdElt));
182 } else {
183 m_size = sizeof(CacheHashIdElt);
184 m_tail = static_cast<CacheHashIdElt *>(m_base)->getTailPtr();
185 }
186 }
187 if (PARSE_SUCCESS == zret)
188 m_base = ptr;
189 return zret;
190 }
191 // ------------------------------------------------------
192 inline CapabilityElt::Type
getCapType() const193 CapabilityElt::getCapType() const
194 {
195 return static_cast<Type>(ntohs(m_cap_type));
196 }
197
198 inline CapabilityElt &
setCapType(Type cap)199 CapabilityElt::setCapType(Type cap)
200 {
201 m_cap_type = static_cast<Type>(htons(cap));
202 return *this;
203 }
204
205 inline uint32_t
getCapData() const206 CapabilityElt::getCapData() const
207 {
208 return ntohl(m_cap_data);
209 }
210
211 inline CapabilityElt &
setCapData(uint32_t data)212 CapabilityElt::setCapData(uint32_t data)
213 {
214 m_cap_data = htonl(data);
215 return *this;
216 }
217
CapabilityElt()218 CapabilityElt::CapabilityElt() {}
219
CapabilityElt(Type cap,uint32_t data)220 CapabilityElt::CapabilityElt(Type cap, uint32_t data)
221 {
222 this->setCapType(cap);
223 this->setCapData(data);
224 m_cap_length = htons(sizeof(uint32_t));
225 }
226 // ------------------------------------------------------
227 inline uint32_t
getf_src_addr() const228 ValueElt::getf_src_addr() const
229 {
230 return ntohl(m_src_addr);
231 }
232
233 inline ValueElt &
setf_src_addr(uint32_t addr)234 ValueElt::setf_src_addr(uint32_t addr)
235 {
236 m_src_addr = htonl(addr);
237 return *this;
238 }
239
240 inline uint32_t
getDstAddr() const241 ValueElt::getDstAddr() const
242 {
243 return ntohl(m_dst_addr);
244 }
245
246 inline ValueElt &
setf_dst_addr(uint32_t addr)247 ValueElt::setf_dst_addr(uint32_t addr)
248 {
249 m_dst_addr = htonl(addr);
250 return *this;
251 }
252
253 inline uint16_t
getf_src_port() const254 ValueElt::getf_src_port() const
255 {
256 return ntohs(m_src_port);
257 }
258
259 inline ValueElt &
setf_src_port(uint16_t port)260 ValueElt::setf_src_port(uint16_t port)
261 {
262 m_src_port = htons(port);
263 return *this;
264 }
265
266 inline uint16_t
getDstPort() const267 ValueElt::getDstPort() const
268 {
269 return ntohs(m_dst_port);
270 }
271
272 inline ValueElt &
setf_dst_port(uint16_t port)273 ValueElt::setf_dst_port(uint16_t port)
274 {
275 m_dst_port = htons(port);
276 return *this;
277 }
278
279 inline uint32_t
getCacheAddr() const280 ValueElt::getCacheAddr() const
281 {
282 return ntohl(m_cache_addr);
283 }
284
285 inline ValueElt &
setCacheAddr(uint32_t addr)286 ValueElt::setCacheAddr(uint32_t addr)
287 {
288 m_cache_addr = htonl(addr);
289 return *this;
290 }
291 // ------------------------------------------------------
292 MaskValueSetElt &
addValue(uint32_t cacheAddr,uint32_t srcAddr,uint32_t dstAddr,uint16_t srcPort,uint16_t dstPort)293 MaskValueSetElt::addValue(uint32_t cacheAddr, uint32_t srcAddr, uint32_t dstAddr, uint16_t srcPort, uint16_t dstPort)
294 {
295 uint32_t idx = ntohl(m_count);
296 new (this->values() + idx) ValueElt(cacheAddr, srcAddr, dstAddr, srcPort, dstPort);
297 m_count = htonl(idx + 1);
298 return *this;
299 }
300
301 size_t
getVarSize() const302 MaskAssignElt::getVarSize() const
303 {
304 size_t zret = 0;
305 int n = this->getCount();
306
307 MaskValueSetElt const *set = reinterpret_cast<MaskValueSetElt const *>(this + 1);
308 while (n--) {
309 size_t k = set->getSize();
310 zret += k;
311 set = reinterpret_cast<MaskValueSetElt const *>(reinterpret_cast<char const *>(set) + k);
312 }
313 return zret;
314 }
315
316 HashAssignElt &
round_robin_assign()317 HashAssignElt::round_robin_assign()
318 {
319 uint32_t v_caches = this->getCount();
320 Bucket *buckets = this->getBucketBase();
321 if (1 == v_caches)
322 memset(buckets, 0, sizeof(Bucket) * N_BUCKETS);
323 else { // Assign round robin.
324 size_t x = 0;
325 for (Bucket *spot = buckets, *limit = spot + N_BUCKETS; spot < limit; ++spot) {
326 spot->m_idx = x;
327 spot->m_alt = 0;
328 x = (x + 1) % v_caches;
329 }
330 }
331 return *this;
332 }
333
334 RouterAssignListElt &
updateRouterId(uint32_t addr,uint32_t rcvid,uint32_t cno)335 RouterAssignListElt::updateRouterId(uint32_t addr, uint32_t rcvid, uint32_t cno)
336 {
337 uint32_t n = this->getCount();
338 RouterAssignElt *elt = access_array<RouterAssignElt>(this + 1);
339 for (uint32_t i = 0; i < n; ++i, ++elt) {
340 if (addr == elt->getAddr()) {
341 elt->setChangeNumber(cno).setRecvId(rcvid);
342 break;
343 }
344 }
345 return *this;
346 }
347 // ------------------------------------------------------
348 message_type_t
getType()349 MsgHeaderComp::getType()
350 {
351 return static_cast<message_type_t>(get_field(&raw_t::m_type, m_base));
352 }
353
354 uint16_t
getVersion()355 MsgHeaderComp::getVersion()
356 {
357 return get_field(&raw_t::m_version, m_base);
358 }
359
360 uint16_t
getLength()361 MsgHeaderComp::getLength()
362 {
363 return get_field(&raw_t::m_length, m_base);
364 }
365
366 MsgHeaderComp &
setType(message_type_t type)367 MsgHeaderComp::setType(message_type_t type)
368 {
369 set_field(&raw_t::m_type, m_base, type);
370 return *this;
371 }
372
373 MsgHeaderComp &
setVersion(uint16_t version)374 MsgHeaderComp::setVersion(uint16_t version)
375 {
376 set_field(&raw_t::m_version, m_base, version);
377 return *this;
378 }
379
380 MsgHeaderComp &
setLength(uint16_t length)381 MsgHeaderComp::setLength(uint16_t length)
382 {
383 set_field(&raw_t::m_length, m_base, length);
384 return *this;
385 }
386
387 size_t
calcSize()388 MsgHeaderComp::calcSize()
389 {
390 return sizeof(raw_t);
391 }
392
393 MsgHeaderComp &
fill(MsgBuffer & buffer,message_type_t t)394 MsgHeaderComp::fill(MsgBuffer &buffer, message_type_t t)
395 {
396 size_t comp_size = this->calcSize();
397 if (buffer.getSpace() < comp_size)
398 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
399 m_base = buffer.getTail();
400 buffer.use(comp_size);
401 this->setType(t).setVersion(VERSION).setLength(0);
402 return *this;
403 }
404
405 int
parse(MsgBuffer & base)406 MsgHeaderComp::parse(MsgBuffer &base)
407 {
408 int zret = PARSE_SUCCESS;
409 size_t comp_size = this->calcSize();
410 if (base.getSpace() < comp_size) {
411 zret = PARSE_BUFFER_TOO_SMALL;
412 } else {
413 m_base = base.getTail();
414 // Length field puts end of message past end of buffer.
415 if (this->getLength() + comp_size > base.getSpace()) {
416 zret = PARSE_MSG_TOO_BIG;
417 } else if (INVALID_MSG_TYPE == this->toMsgType(get_field(&raw_t::m_type, m_base))) {
418 zret = PARSE_COMP_TYPE_INVALID;
419 } else {
420 base.use(comp_size);
421 }
422 }
423 return zret;
424 }
425 // ------------------------------------------------------
426 SecurityComp::Key SecurityComp::m_default_key;
427 SecurityComp::Option SecurityComp::m_default_opt = SECURITY_NONE;
428
429 SecurityComp::Option
getOption() const430 SecurityComp::getOption() const
431 {
432 return static_cast<Option>(get_field(&RawNone::m_option, m_base));
433 }
434
435 SecurityComp &
setOption(Option opt)436 SecurityComp::setOption(Option opt)
437 {
438 set_field(&RawNone::m_option, m_base, static_cast<uint32_t>(opt));
439 return *this;
440 }
441
442 SecurityComp &
setKey(char const * key)443 SecurityComp::setKey(char const *key)
444 {
445 m_local_key = true;
446 ink_strlcpy(m_key, key, KEY_SIZE);
447 return *this;
448 }
449
450 void
setDefaultKey(char const * key)451 SecurityComp::setDefaultKey(char const *key)
452 {
453 ink_strlcpy(m_default_key, key, KEY_SIZE);
454 }
455
456 SecurityComp &
fill(MsgBuffer & buffer,Option opt)457 SecurityComp::fill(MsgBuffer &buffer, Option opt)
458 {
459 size_t comp_size = this->calcSize(opt);
460
461 if (buffer.getSpace() < comp_size)
462 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
463
464 m_base = buffer.getTail();
465
466 this->setType(COMP_TYPE).setLength(comp_size - sizeof(super::raw_t)).setOption(opt);
467
468 if (SECURITY_NONE != opt) {
469 RawMD5::HashData &data = access_field(&RawMD5::m_data, m_base);
470 memset(data, 0, sizeof(data));
471 }
472
473 buffer.use(comp_size);
474 return *this;
475 }
476
477 SecurityComp &
secure(MsgBuffer const & msg)478 SecurityComp::secure(MsgBuffer const &msg)
479 {
480 if (SECURITY_MD5 == this->getOption()) {
481 MD5_CTX ctx;
482 char const *key = m_local_key ? m_key : m_default_key;
483 MD5_Init(&ctx);
484 MD5_Update(&ctx, key, KEY_SIZE);
485 MD5_Update(&ctx, msg.getBase(), msg.getCount());
486 MD5_Final(access_field(&RawMD5::m_data, m_base), &ctx);
487 }
488 return *this;
489 }
490
491 bool
validate(MsgBuffer const & msg) const492 SecurityComp::validate(MsgBuffer const &msg) const
493 {
494 bool zret = true;
495 if (SECURITY_MD5 == this->getOption()) {
496 RawMD5::HashData save;
497 RawMD5::HashData &org = const_cast<RawMD5::HashData &>(access_field(&RawMD5::m_data, m_base));
498 MD5_CTX ctx;
499 char const *key = m_local_key ? m_key : m_default_key;
500 // save the original hash aside.
501 memcpy(save, org, sizeof(save));
502 // zero out the component hash area to compute the hash.
503 memset(org, 0, sizeof(org));
504 // Compute hash in to hash area.
505 MD5_Init(&ctx);
506 MD5_Update(&ctx, key, KEY_SIZE);
507 MD5_Update(&ctx, msg.getBase(), msg.getCount());
508 MD5_Final(org, &ctx);
509 // check hash.
510 zret = 0 == memcmp(org, save, sizeof(save));
511 // restore original data.
512 memcpy(org, save, sizeof(save));
513 }
514 return zret;
515 }
516
517 int
parse(MsgBuffer & buffer)518 SecurityComp::parse(MsgBuffer &buffer)
519 {
520 int zret = PARSE_SUCCESS;
521 if (buffer.getSpace() < sizeof(raw_t))
522 zret = PARSE_BUFFER_TOO_SMALL;
523 else {
524 m_base = buffer.getTail();
525 zret = this->checkHeader(buffer, COMP_TYPE);
526 if (PARSE_SUCCESS == zret) {
527 Option opt = this->getOption();
528 if (SECURITY_NONE != opt && SECURITY_MD5 != opt)
529 zret = PARSE_COMP_INVALID;
530 else {
531 size_t comp_size = this->calcSize(opt);
532 if (this->getLength() != comp_size - sizeof(super::raw_t))
533 zret = PARSE_COMP_WRONG_SIZE;
534 else
535 buffer.use(comp_size);
536 }
537 }
538 }
539 return zret;
540 }
541 // ------------------------------------------------------
542
543 ServiceComp &
setPort(int idx,uint16_t port)544 ServiceComp::setPort(int idx, uint16_t port)
545 {
546 this->access()->setPort(idx, port);
547 m_port_count = std::max(m_port_count, idx);
548 return *this;
549 }
550
551 ServiceComp &
addPort(uint16_t port)552 ServiceComp::addPort(uint16_t port)
553 {
554 if (m_port_count < static_cast<int>(ServiceGroup::N_PORTS))
555 this->access()->setPort(m_port_count++, port);
556 return *this;
557 }
558
559 ServiceComp &
clearPorts()560 ServiceComp::clearPorts()
561 {
562 this->access()->clearPorts();
563 m_port_count = 0;
564 return *this;
565 }
566
567 ServiceComp &
fill(MsgBuffer & buffer,ServiceGroup const & svc)568 ServiceComp::fill(MsgBuffer &buffer, ServiceGroup const &svc)
569 {
570 size_t comp_size = this->calcSize();
571
572 if (buffer.getSpace() < comp_size)
573 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
574
575 m_base = buffer.getTail();
576
577 this->setType(COMP_TYPE).setLength(comp_size - sizeof(super::raw_t));
578
579 // Cast buffer to our serialized type, then cast to ServiceGroup
580 // to get offset of that part of the serialization storage.
581 memcpy(
582 // This generates a gcc warning, but the next line doesn't. Yay.
583 // static_cast<ServiceGroup*>(reinterpret_cast<raw_t*>(m_base)),
584 &static_cast<ServiceGroup &>(*reinterpret_cast<raw_t *>(m_base)), &svc, sizeof(svc));
585 buffer.use(comp_size);
586 return *this;
587 }
588
589 int
parse(MsgBuffer & buffer)590 ServiceComp::parse(MsgBuffer &buffer)
591 {
592 int zret = PARSE_SUCCESS;
593 size_t comp_size = this->calcSize();
594 if (buffer.getSpace() < comp_size)
595 zret = PARSE_BUFFER_TOO_SMALL;
596 else {
597 m_base = buffer.getTail();
598 zret = this->checkHeader(buffer, COMP_TYPE);
599 if (PARSE_SUCCESS == zret) {
600 ServiceGroup::Type svc = this->getSvcType();
601 if (ServiceGroup::DYNAMIC != svc && ServiceGroup::STANDARD != svc)
602 zret = PARSE_COMP_INVALID;
603 else if (this->getLength() != comp_size - sizeof(super::raw_t))
604 zret = PARSE_COMP_WRONG_SIZE;
605 else
606 buffer.use(comp_size);
607 }
608 }
609 return zret;
610 }
611 // ------------------------------------------------------
612 RouterIdElt &
idElt()613 RouterIdComp::idElt()
614 {
615 return access_field(&raw_t::m_id, m_base);
616 }
617
618 RouterIdElt const &
idElt() const619 RouterIdComp::idElt() const
620 {
621 return access_field(&raw_t::m_id, m_base);
622 }
623
624 RouterIdComp &
setIdElt(uint32_t addr,uint32_t recv_id)625 RouterIdComp::setIdElt(uint32_t addr, uint32_t recv_id)
626 {
627 this->idElt().setAddr(addr).setRecvId(recv_id);
628 return *this;
629 }
630
631 uint32_t
getAddr() const632 RouterIdComp::getAddr() const
633 {
634 return this->idElt().getAddr();
635 }
636
637 RouterIdComp &
setAddr(uint32_t addr)638 RouterIdComp::setAddr(uint32_t addr)
639 {
640 this->idElt().setAddr(addr);
641 return *this;
642 }
643
644 uint32_t
getRecvId() const645 RouterIdComp::getRecvId() const
646 {
647 return this->idElt().getRecvId();
648 }
649 inline RouterIdComp &
setRecvId(uint32_t id)650 RouterIdComp::setRecvId(uint32_t id)
651 {
652 this->idElt().setRecvId(id);
653 return *this;
654 }
655
656 uint32_t
getToAddr() const657 RouterIdComp::getToAddr() const
658 {
659 return access_field(&raw_t::m_to_addr, m_base);
660 }
661
662 RouterIdComp &
setToAddr(uint32_t addr)663 RouterIdComp::setToAddr(uint32_t addr)
664 {
665 access_field(&raw_t::m_to_addr, m_base) = addr;
666 return *this;
667 }
668
669 uint32_t
getFromCount() const670 RouterIdComp::getFromCount() const
671 {
672 return get_field(&raw_t::m_from_count, m_base);
673 }
674
675 uint32_t
getFromAddr(int idx) const676 RouterIdComp::getFromAddr(int idx) const
677 {
678 return access_array<uint32_t>(m_base + sizeof(raw_t))[idx];
679 }
680
681 RouterIdComp &
setFromAddr(int idx,uint32_t addr)682 RouterIdComp::setFromAddr(int idx, uint32_t addr)
683 {
684 access_array<uint32_t>(m_base + sizeof(raw_t))[idx] = addr;
685 return *this;
686 }
687
688 int
findFromAddr(uint32_t addr)689 RouterIdComp::findFromAddr(uint32_t addr)
690 {
691 int n = this->getFromCount();
692 uint32_t *addrs = access_array<uint32_t>(m_base + sizeof(raw_t)) + n;
693 while (n-- != 0 && *--addrs != addr)
694 ;
695 return n;
696 }
697
698 RouterIdComp &
fill(MsgBuffer & buffer,size_t n_caches)699 RouterIdComp::fill(MsgBuffer &buffer, size_t n_caches)
700 {
701 size_t comp_size = this->calcSize(n_caches);
702 if (buffer.getSpace() < comp_size)
703 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
704
705 m_base = buffer.getTail();
706
707 this->setType(COMP_TYPE);
708 set_field(&raw_t::m_from_count, m_base, n_caches);
709 this->setLength(comp_size - sizeof(super::raw_t));
710 buffer.use(comp_size);
711
712 return *this;
713 }
714
715 RouterIdComp &
fillSingleton(MsgBuffer & buffer,uint32_t addr,uint32_t recv_count,uint32_t to_addr,uint32_t from_addr)716 RouterIdComp::fillSingleton(MsgBuffer &buffer, uint32_t addr, uint32_t recv_count, uint32_t to_addr, uint32_t from_addr)
717 {
718 size_t comp_size = this->calcSize(1);
719
720 if (buffer.getSpace() < comp_size)
721 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
722
723 m_base = buffer.getTail();
724
725 this->setType(COMP_TYPE).setIdElt(addr, recv_count).setToAddr(to_addr).setFromAddr(0, from_addr);
726
727 set_field(&raw_t::m_from_count, m_base, 1);
728
729 this->setLength(comp_size - sizeof(super::raw_t));
730 buffer.use(comp_size);
731
732 return *this;
733 }
734
735 int
parse(MsgBuffer & buffer)736 RouterIdComp::parse(MsgBuffer &buffer)
737 {
738 int zret = PARSE_SUCCESS;
739 if (buffer.getSpace() < sizeof(raw_t))
740 zret = PARSE_BUFFER_TOO_SMALL;
741 else {
742 m_base = buffer.getTail();
743 zret = this->checkHeader(buffer, COMP_TYPE);
744 if (PARSE_SUCCESS == zret) {
745 size_t comp_size = this->calcSize(this->getFromCount());
746 if (this->getLength() != comp_size - sizeof(super::raw_t))
747 zret = PARSE_COMP_WRONG_SIZE;
748 else
749 buffer.use(comp_size);
750 }
751 }
752 return zret;
753 }
754 // ------------------------------------------------------
755 AssignmentKeyElt &
keyElt()756 RouterViewComp::keyElt()
757 {
758 return access_field(&raw_t::m_key, m_base);
759 }
760
761 AssignmentKeyElt const &
keyElt() const762 RouterViewComp::keyElt() const
763 {
764 return access_field(&raw_t::m_key, m_base);
765 }
766
767 uint32_t
getChangeNumber() const768 RouterViewComp::getChangeNumber() const
769 {
770 return get_field(&raw_t::m_change_number, m_base);
771 }
772
773 RouterViewComp &
setChangeNumber(uint32_t n)774 RouterViewComp::setChangeNumber(uint32_t n)
775 {
776 set_field(&raw_t::m_change_number, m_base, n);
777 return *this;
778 }
779
780 // This is untainted because an overall size check is done when the packet is read. If any of the
781 // counts are bogus, that size check will fail.
782 // coverity[ -tainted_data_return]
783 uint32_t
getCacheCount() const784 RouterViewComp::getCacheCount() const
785 {
786 return ntohl(*m_cache_count);
787 }
788
789 // This is untainted because an overall size check is done when the packet is read. If any of the
790 // counts are bogus, that size check will fail.
791 // coverity[ -tainted_data_return]
792 uint32_t
getRouterCount() const793 RouterViewComp::getRouterCount() const
794 {
795 return get_field(&raw_t::m_router_count, m_base);
796 }
797
798 CacheIdBox &
cacheId(int idx)799 RouterViewComp::cacheId(int idx)
800 {
801 return m_cache_ids[idx];
802 }
803
804 uint32_t
getRouterAddr(int idx) const805 RouterViewComp::getRouterAddr(int idx) const
806 {
807 return access_array<uint32_t>(m_base + sizeof(raw_t))[idx];
808 }
809
810 RouterViewComp &
setRouterAddr(int idx,uint32_t addr)811 RouterViewComp::setRouterAddr(int idx, uint32_t addr)
812 {
813 access_array<uint32_t>(m_base + sizeof(raw_t))[idx] = addr;
814 return *this;
815 }
816
817 uint32_t *
calc_cache_count_ptr()818 RouterViewComp::calc_cache_count_ptr()
819 {
820 return reinterpret_cast<uint32_t *>(m_base + sizeof(raw_t) + this->getRouterCount() * sizeof(uint32_t));
821 }
822
823 RouterViewComp &
fill(MsgBuffer & buffer,int n_routers,int n_caches)824 RouterViewComp::fill(MsgBuffer &buffer, int n_routers, int n_caches)
825 {
826 // TBD: This isn't right since the upgrade to mask support
827 // because the size isn't a static function of the router and
828 // cache count anymore.
829 size_t comp_size = sizeof(raw_t);
830
831 if (buffer.getSpace() < comp_size)
832 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
833
834 m_base = buffer.getTail();
835
836 this->setType(COMP_TYPE);
837
838 // No setf for this field, hand pack it.
839 set_field(&raw_t::m_router_count, m_base, n_routers);
840 // Set the pointer to the count of caches.
841 m_cache_count = this->calc_cache_count_ptr();
842 // No setf, go direct.
843 *m_cache_count = htonl(n_caches);
844
845 this->setLength(comp_size - HEADER_SIZE);
846 buffer.use(comp_size);
847
848 return *this;
849 }
850
851 int
parse(MsgBuffer & buffer)852 RouterViewComp::parse(MsgBuffer &buffer)
853 {
854 int zret = PARSE_SUCCESS;
855 if (buffer.getSpace() < sizeof(raw_t))
856 zret = PARSE_BUFFER_TOO_SMALL;
857 else {
858 m_base = buffer.getTail();
859 zret = this->checkHeader(buffer, COMP_TYPE);
860 if (PARSE_SUCCESS == zret) {
861 uint32_t ncaches; // # of caches.
862 if (this->getRouterCount() > MAX_ROUTERS)
863 zret = PARSE_MSG_INVALID;
864 // check if cache count is past end of buffer
865 else if (static_cast<void *>(m_cache_count = this->calc_cache_count_ptr()) >=
866 static_cast<void *>(buffer.getBase() + buffer.getSize()))
867 zret = PARSE_COMP_WRONG_SIZE, log(LVL_DEBUG, "I_SEE_YOU: cache counter past end of buffer");
868 else if ((ncaches = this->getCacheCount()) > MAX_CACHES)
869 zret = PARSE_MSG_INVALID;
870 else {
871 size_t comp_size = reinterpret_cast<char *>(m_cache_count + 1) - m_base;
872 // Walk the cache ID elements.
873 MsgBuffer spot(buffer);
874 CacheIdBox *box = m_cache_ids;
875 uint32_t idx = 0;
876 spot.use(comp_size);
877 while (idx < ncaches && PARSE_SUCCESS == (zret = box->parse(spot))) {
878 size_t k = box->getSize();
879 spot.use(k);
880 comp_size += k;
881 ++box;
882 ++idx;
883 }
884 if (PARSE_SUCCESS == zret)
885 buffer.use(comp_size);
886 }
887 }
888 }
889 return zret;
890 }
891 // ------------------------------------------------------
892 CacheIdComp &
fill(MsgBuffer & base,CacheIdBox const & src)893 CacheIdComp::fill(MsgBuffer &base, CacheIdBox const &src)
894 {
895 size_t comp_size = src.getSize() + HEADER_SIZE;
896
897 if (base.getSpace() < comp_size)
898 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
899
900 m_base = base.getTail();
901 this->setType(COMP_TYPE).setLength(comp_size - HEADER_SIZE);
902 m_box.fill(&(access_field(&raw_t::m_id, m_base)), src);
903 base.use(comp_size);
904 return *this;
905 }
906
907 int
parse(MsgBuffer & buffer)908 CacheIdComp::parse(MsgBuffer &buffer)
909 {
910 int zret = PARSE_SUCCESS;
911 if (buffer.getSpace() < sizeof(raw_t))
912 zret = PARSE_BUFFER_TOO_SMALL;
913 else {
914 m_base = buffer.getTail();
915 zret = this->checkHeader(buffer, COMP_TYPE);
916 if (PARSE_SUCCESS == zret) {
917 MsgBuffer tmp(buffer);
918 tmp.use(reinterpret_cast<char *>(&(access_field(&raw_t::m_id, m_base))) - m_base);
919 zret = m_box.parse(tmp);
920 if (PARSE_SUCCESS == zret) {
921 size_t comp_size = HEADER_SIZE + m_box.getSize();
922 if (this->getLength() != comp_size - HEADER_SIZE)
923 zret = PARSE_COMP_WRONG_SIZE;
924 else
925 buffer.use(comp_size);
926 }
927 }
928 }
929 return zret;
930 }
931 // ------------------------------------------------------
932 uint32_t
getChangeNumber() const933 CacheViewComp::getChangeNumber() const
934 {
935 return get_field(&raw_t::m_change_number, m_base);
936 }
937
938 CacheViewComp &
setChangeNumber(uint32_t n)939 CacheViewComp::setChangeNumber(uint32_t n)
940 {
941 set_field(&raw_t::m_change_number, m_base, n);
942 return *this;
943 }
944
945 uint32_t
getRouterCount() const946 CacheViewComp::getRouterCount() const
947 {
948 return get_field(&raw_t::m_router_count, m_base);
949 }
950
951 uint32_t
getCacheCount() const952 CacheViewComp::getCacheCount() const
953 {
954 return ntohl(*m_cache_count);
955 }
956
957 uint32_t
getCacheAddr(int idx) const958 CacheViewComp::getCacheAddr(int idx) const
959 {
960 return ntohl(m_cache_count[idx + 1]);
961 }
962
963 CacheViewComp &
setCacheAddr(int idx,uint32_t addr)964 CacheViewComp::setCacheAddr(int idx, uint32_t addr)
965 {
966 m_cache_count[idx + 1] = addr;
967 return *this;
968 }
969
970 RouterIdElt *
atf_router_array()971 CacheViewComp::atf_router_array()
972 {
973 return reinterpret_cast<RouterIdElt *>(m_base + sizeof(raw_t));
974 }
975
976 RouterIdElt &
routerElt(int idx)977 CacheViewComp::routerElt(int idx)
978 {
979 return this->atf_router_array()[idx];
980 }
981
982 RouterIdElt *
findf_router_elt(uint32_t addr)983 CacheViewComp::findf_router_elt(uint32_t addr)
984 {
985 for (RouterIdElt *rtr = this->atf_router_array(), *limit = rtr + this->getRouterCount(); rtr < limit; ++rtr) {
986 if (rtr->getAddr() == addr)
987 return rtr;
988 }
989 return 0;
990 }
991
992 size_t
calcSize(int n_routers,int n_caches)993 CacheViewComp::calcSize(int n_routers, int n_caches)
994 {
995 return sizeof(raw_t) + n_routers * sizeof(RouterIdElt) + sizeof(uint32_t) + n_caches * sizeof(uint32_t);
996 }
997
998 CacheViewComp &
fill(MsgBuffer & buffer,detail::cache::GroupData const & group)999 CacheViewComp::fill(MsgBuffer &buffer, detail::cache::GroupData const &group)
1000 {
1001 int i;
1002 size_t n_routers = group.m_routers.size();
1003 size_t n_caches = group.m_caches.size();
1004 size_t comp_size = this->calcSize(n_routers, n_caches);
1005
1006 if (buffer.getSpace() < comp_size)
1007 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
1008
1009 m_base = buffer.getTail();
1010
1011 this->setType(COMP_TYPE).setChangeNumber(group.m_generation);
1012
1013 set_field(&raw_t::m_router_count, m_base, n_routers);
1014 // Set the pointer to the count of caches.
1015 m_cache_count = reinterpret_cast<uint32_t *>(m_base + sizeof(raw_t) + n_routers * sizeof(RouterIdElt));
1016 *m_cache_count = htonl(n_caches); // set the actual count.
1017
1018 // Fill routers.
1019 i = 0;
1020 for (detail::cache::RouterBag::const_iterator spot = group.m_routers.begin(), limit = group.m_routers.end(); spot != limit;
1021 ++spot, ++i) {
1022 this->routerElt(i).setAddr(spot->m_addr).setRecvId(spot->m_recv.m_sn);
1023 }
1024
1025 // fill caches.
1026 i = 0;
1027 for (detail::cache::CacheBag::const_iterator spot = group.m_caches.begin(), limit = group.m_caches.end(); spot != limit;
1028 ++spot, ++i) {
1029 this->setCacheAddr(i, spot->idAddr());
1030 }
1031
1032 this->setLength(comp_size - sizeof(super::raw_t));
1033 buffer.use(comp_size);
1034 return *this;
1035 }
1036
1037 int
parse(MsgBuffer & buffer)1038 CacheViewComp::parse(MsgBuffer &buffer)
1039 {
1040 int zret = PARSE_SUCCESS;
1041 if (buffer.getSpace() < sizeof(raw_t))
1042 zret = PARSE_BUFFER_TOO_SMALL;
1043 else {
1044 m_base = buffer.getTail();
1045 zret = this->checkHeader(buffer, COMP_TYPE);
1046 if (PARSE_SUCCESS == zret) {
1047 m_cache_count = reinterpret_cast<uint32_t *>(m_base + sizeof(raw_t) + this->getRouterCount() * sizeof(RouterIdElt));
1048 size_t comp_size = this->calcSize(this->getRouterCount(), this->getCacheCount());
1049 if (this->getLength() != comp_size - sizeof(super::raw_t))
1050 zret = PARSE_COMP_WRONG_SIZE;
1051 else
1052 buffer.use(comp_size);
1053 }
1054 }
1055 return zret;
1056 }
1057 // ------------------------------------------------------
1058 AssignmentKeyElt &
keyElt()1059 AssignInfoComp::keyElt()
1060 {
1061 return access_field(&raw_t::m_key, m_base);
1062 }
1063
1064 AssignmentKeyElt const &
keyElt() const1065 AssignInfoComp::keyElt() const
1066 {
1067 return access_field(&raw_t::m_key, m_base);
1068 }
1069
1070 uint32_t
getKeyChangeNumber() const1071 AssignInfoComp::getKeyChangeNumber() const
1072 {
1073 return access_field(&raw_t::m_key, m_base).getChangeNumber();
1074 }
1075
1076 AssignInfoComp &
setKeyChangeNumber(uint32_t n)1077 AssignInfoComp::setKeyChangeNumber(uint32_t n)
1078 {
1079 access_field(&raw_t::m_key, m_base).setChangeNumber(n);
1080 return *this;
1081 }
1082
1083 uint32_t
getKeyAddr() const1084 AssignInfoComp::getKeyAddr() const
1085 {
1086 return access_field(&raw_t::m_key, m_base).getAddr();
1087 }
1088
1089 AssignInfoComp &
setKeyAddr(uint32_t addr)1090 AssignInfoComp::setKeyAddr(uint32_t addr)
1091 {
1092 access_field(&raw_t::m_key, m_base).setAddr(addr);
1093 return *this;
1094 }
1095
1096 uint32_t
getRouterCount() const1097 AssignInfoComp::getRouterCount() const
1098 {
1099 return access_field(&raw_t::m_routers, m_base).getCount();
1100 }
1101
1102 RouterAssignElt &
routerElt(int idx)1103 AssignInfoComp::routerElt(int idx)
1104 {
1105 return access_field(&raw_t::m_routers, m_base).elt(idx);
1106 }
1107
1108 uint32_t
getCacheCount() const1109 AssignInfoComp::getCacheCount() const
1110 {
1111 return ntohl(*m_cache_count);
1112 }
1113
1114 uint32_t
getCacheAddr(int idx) const1115 AssignInfoComp::getCacheAddr(int idx) const
1116 {
1117 return m_cache_count[idx + 1];
1118 }
1119
1120 AssignInfoComp &
setCacheAddr(int idx,uint32_t addr)1121 AssignInfoComp::setCacheAddr(int idx, uint32_t addr)
1122 {
1123 m_cache_count[idx + 1] = addr;
1124 return *this;
1125 }
1126
1127 size_t
calcSize(int n_routers,int n_caches)1128 AssignInfoComp::calcSize(int n_routers, int n_caches)
1129 {
1130 return sizeof(raw_t) + RouterAssignListElt::calcVarSize(n_routers) + HashAssignElt::calcSize(n_caches);
1131 }
1132
1133 uint32_t *
calcCacheCountPtr()1134 AssignInfoComp::calcCacheCountPtr()
1135 {
1136 return reinterpret_cast<uint32_t *>(m_base + sizeof(raw_t) + access_field(&raw_t::m_routers, m_base).getVarSize());
1137 }
1138
1139 AssignInfoComp::Bucket *
calcBucketPtr()1140 AssignInfoComp::calcBucketPtr()
1141 {
1142 return reinterpret_cast<Bucket *>(reinterpret_cast<char *>(m_cache_count) + sizeof(uint32_t) * (1 + this->getCacheCount()));
1143 }
1144
1145 AssignInfoComp &
fill(MsgBuffer & buffer,detail::Assignment const & assign)1146 AssignInfoComp::fill(MsgBuffer &buffer, detail::Assignment const &assign)
1147 {
1148 RouterAssignListElt const &ralist = assign.getRouterList();
1149 HashAssignElt const &ha = assign.getHash();
1150 size_t n_routers = ralist.getCount();
1151 size_t n_caches = ha.getCount();
1152 size_t comp_size = this->calcSize(n_routers, n_caches);
1153
1154 if (buffer.getSpace() < comp_size)
1155 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
1156
1157 m_base = buffer.getTail();
1158
1159 this->setType(COMP_TYPE);
1160 this->keyElt() = assign.getKey();
1161 memcpy(&(access_field(&raw_t::m_routers, m_base)), &ralist, ralist.getSize());
1162 // Set the pointer to the count of caches and write the count.
1163 m_cache_count = this->calcCacheCountPtr();
1164 memcpy(m_cache_count, &ha, ha.getSize());
1165
1166 this->setLength(comp_size - HEADER_SIZE);
1167 buffer.use(comp_size);
1168
1169 return *this;
1170 }
1171
1172 int
parse(MsgBuffer & buffer)1173 AssignInfoComp::parse(MsgBuffer &buffer)
1174 {
1175 int zret = PARSE_SUCCESS;
1176 if (buffer.getSpace() < HEADER_SIZE)
1177 zret = PARSE_BUFFER_TOO_SMALL;
1178 else {
1179 m_base = buffer.getTail();
1180 zret = this->checkHeader(buffer, COMP_TYPE);
1181 if (PARSE_SUCCESS == zret) {
1182 int n_routers = this->getRouterCount();
1183 int n_caches;
1184 m_cache_count = this->calcCacheCountPtr();
1185 n_caches = this->getCacheCount();
1186 m_buckets = this->calcBucketPtr();
1187 size_t comp_size = this->calcSize(n_routers, n_caches);
1188 if (this->getLength() != comp_size - HEADER_SIZE)
1189 zret = PARSE_COMP_WRONG_SIZE;
1190 else
1191 buffer.use(comp_size);
1192 }
1193 }
1194 if (PARSE_SUCCESS != zret)
1195 m_base = 0;
1196 return zret;
1197 }
1198
1199 AssignmentKeyElt &
keyElt()1200 AltAssignComp::keyElt()
1201 {
1202 return access_field(&raw_t::m_key, m_base);
1203 }
1204
1205 AssignmentKeyElt const &
keyElt() const1206 AltAssignComp::keyElt() const
1207 {
1208 return access_field(&raw_t::m_key, m_base);
1209 }
1210
1211 void *
calcVarPtr()1212 AltAssignComp::calcVarPtr()
1213 {
1214 return reinterpret_cast<void *>(m_base + sizeof(raw_t) + access_field(&raw_t::m_routers, m_base).getVarSize());
1215 }
1216
1217 uint32_t
getRouterCount() const1218 AltAssignComp::getRouterCount() const
1219 {
1220 return access_field(&raw_t::m_routers, m_base).getCount();
1221 }
1222
1223 uint32_t
getCacheCount() const1224 AltHashAssignComp::getCacheCount() const
1225 {
1226 return ntohl(*m_cache_count);
1227 }
1228
1229 size_t
calcSize(int n_routers,int n_caches)1230 AltHashAssignComp::calcSize(int n_routers, int n_caches)
1231 {
1232 return sizeof(raw_t) + RouterAssignListElt::calcVarSize(n_routers) + HashAssignElt::calcSize(n_caches);
1233 }
1234
1235 AltHashAssignComp &
fill(MsgBuffer & buffer,detail::Assignment const & assign)1236 AltHashAssignComp::fill(MsgBuffer &buffer, detail::Assignment const &assign)
1237 {
1238 RouterAssignListElt const &ralist = assign.getRouterList();
1239 HashAssignElt const &ha = assign.getHash();
1240 size_t n_routers = ralist.getCount();
1241 size_t n_caches = ha.getCount();
1242 size_t comp_size = this->calcSize(n_routers, n_caches);
1243
1244 if (buffer.getSpace() < comp_size)
1245 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
1246
1247 m_base = buffer.getTail();
1248
1249 this->setType(COMP_TYPE)
1250 .setLength(comp_size - HEADER_SIZE)
1251 .setAssignType(ALT_HASH_ASSIGNMENT)
1252 .setAssignLength(comp_size - HEADER_SIZE - sizeof(local_header_t));
1253 this->keyElt() = assign.getKey();
1254 memcpy(&(access_field(&raw_t::m_routers, m_base)), &ralist, ralist.getSize());
1255 // Set the pointer to the count of caches and write the count.
1256 m_cache_count = static_cast<uint32_t *>(this->calcVarPtr());
1257 memcpy(m_cache_count, &ha, ha.getSize());
1258
1259 buffer.use(comp_size);
1260
1261 return *this;
1262 }
1263
1264 int
parse(MsgBuffer & buffer)1265 AltHashAssignComp::parse(MsgBuffer &buffer)
1266 {
1267 int zret = PARSE_SUCCESS;
1268 if (buffer.getSpace() < sizeof(raw_t))
1269 zret = PARSE_BUFFER_TOO_SMALL;
1270 else {
1271 m_base = buffer.getTail();
1272 zret = this->checkHeader(buffer, COMP_TYPE);
1273 if (PARSE_SUCCESS == zret) {
1274 int n_routers = this->getRouterCount();
1275 int n_caches;
1276 m_cache_count = static_cast<uint32_t *>(this->calcVarPtr());
1277 n_caches = this->getCacheCount();
1278 size_t comp_size = this->calcSize(n_routers, n_caches);
1279 if (this->getLength() != comp_size - HEADER_SIZE)
1280 zret = PARSE_COMP_WRONG_SIZE;
1281 else
1282 buffer.use(comp_size);
1283 }
1284 }
1285 if (PARSE_SUCCESS != zret)
1286 m_base = 0;
1287 return zret;
1288 }
1289
1290 AltMaskAssignComp &
fill(MsgBuffer & buffer,detail::Assignment const & assign)1291 AltMaskAssignComp::fill(MsgBuffer &buffer, detail::Assignment const &assign)
1292 {
1293 RouterAssignListElt const &ralist = assign.getRouterList();
1294 MaskAssignElt const &ma = assign.getMask();
1295 size_t comp_size = sizeof(raw_t) + ralist.getVarSize() + ma.getSize();
1296
1297 if (buffer.getSpace() < comp_size)
1298 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
1299
1300 m_base = buffer.getTail();
1301
1302 this->setType(COMP_TYPE)
1303 .setLength(comp_size - HEADER_SIZE)
1304 .setAssignType(ALT_MASK_ASSIGNMENT)
1305 .setAssignLength(comp_size - HEADER_SIZE - sizeof(local_header_t));
1306 this->keyElt() = assign.getKey();
1307
1308 memcpy(&(access_field(&raw_t::m_routers, m_base)), &ralist, ralist.getSize());
1309 m_mask_elt = static_cast<MaskAssignElt *>(this->calcVarPtr());
1310 memcpy(m_mask_elt, &ma, ma.getSize());
1311
1312 buffer.use(comp_size);
1313
1314 return *this;
1315 }
1316
1317 int
parse(MsgBuffer & buffer)1318 AltMaskAssignComp::parse(MsgBuffer &buffer)
1319 {
1320 int zret = PARSE_SUCCESS;
1321 if (buffer.getSpace() < sizeof(raw_t))
1322 zret = PARSE_BUFFER_TOO_SMALL;
1323 else {
1324 m_base = buffer.getTail();
1325 zret = this->checkHeader(buffer, COMP_TYPE);
1326 if (PARSE_SUCCESS == zret) {
1327 RouterAssignListElt *ralist = &(access_field(&raw_t::m_routers, m_base));
1328 m_mask_elt = static_cast<MaskAssignElt *>(this->calcVarPtr());
1329 size_t comp_size = sizeof(raw_t) + ralist->getVarSize() + m_mask_elt->getSize();
1330 if (this->getLength() != comp_size - HEADER_SIZE)
1331 zret = PARSE_COMP_WRONG_SIZE;
1332 else
1333 buffer.use(comp_size);
1334 }
1335 }
1336 if (PARSE_SUCCESS != zret)
1337 m_base = 0;
1338 return zret;
1339 }
1340
1341 // ------------------------------------------------------
1342 CmdComp::cmd_t
getCmd() const1343 CmdComp::getCmd() const
1344 {
1345 return static_cast<cmd_t>(get_field(&raw_t::m_cmd, m_base));
1346 }
1347
1348 CmdComp &
setCmd(cmd_t cmd)1349 CmdComp::setCmd(cmd_t cmd)
1350 {
1351 set_field(&raw_t::m_cmd, m_base, cmd);
1352 return *this;
1353 }
1354
1355 uint32_t
getCmdData() const1356 CmdComp::getCmdData() const
1357 {
1358 return get_field(&raw_t::m_cmd_data, m_base);
1359 }
1360
1361 CmdComp &
setCmdData(uint32_t data)1362 CmdComp::setCmdData(uint32_t data)
1363 {
1364 set_field(&raw_t::m_cmd_data, m_base, data);
1365 return *this;
1366 }
1367
1368 inline size_t
calcSize()1369 CmdComp::calcSize()
1370 {
1371 return sizeof(raw_t);
1372 }
1373
1374 CmdComp &
fill(MsgBuffer & buffer,cmd_t cmd,uint32_t data)1375 CmdComp::fill(MsgBuffer &buffer, cmd_t cmd, uint32_t data)
1376 {
1377 size_t comp_size = this->calcSize();
1378
1379 if (buffer.getSpace() < comp_size)
1380 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
1381
1382 m_base = buffer.getTail();
1383
1384 this->setType(COMP_TYPE).setCmd(cmd).setCmdData(data).setLength(sizeof(raw_t) - sizeof(super::raw_t));
1385 // Command length is always the same.
1386 set_field(&raw_t::m_length, m_base, sizeof(uint32_t));
1387 // reinterpret_cast<raw_t*>(m_base)->m_length = htons(sizeof(uint32_t));
1388 return *this;
1389 }
1390
1391 int
parse(MsgBuffer & buffer)1392 CmdComp::parse(MsgBuffer &buffer)
1393 {
1394 int zret = PARSE_SUCCESS;
1395 if (buffer.getSpace() < sizeof(raw_t))
1396 zret = PARSE_BUFFER_TOO_SMALL;
1397 else {
1398 m_base = buffer.getTail();
1399 zret = this->checkHeader(buffer, COMP_TYPE);
1400 if (PARSE_SUCCESS == zret) {
1401 if (this->getLength() + sizeof(super::raw_t) != this->calcSize())
1402 zret = PARSE_COMP_WRONG_SIZE;
1403 }
1404 }
1405 return zret;
1406 }
1407 // ------------------------------------------------------
1408 CapabilityElt &
elt(int idx)1409 CapComp::elt(int idx)
1410 {
1411 return access_array<CapabilityElt>(m_base + sizeof(super::raw_t))[idx];
1412 }
1413
1414 CapabilityElt const &
elt(int idx) const1415 CapComp::elt(int idx) const
1416 {
1417 return access_array<CapabilityElt>(m_base + sizeof(super::raw_t))[idx];
1418 }
1419
1420 void
cache() const1421 CapComp::cache() const
1422 {
1423 uint32_t x; // scratch for bounds checking.
1424 // Reset all values.
1425 m_packet_forward = ServiceGroup::NO_PACKET_STYLE;
1426 m_packet_return = ServiceGroup::NO_PACKET_STYLE;
1427 m_cache_assign = ServiceGroup::NO_CACHE_ASSIGN_STYLE;
1428 if (!m_base)
1429 return; // No data, everything is default.
1430 // Load from data.
1431 for (uint32_t i = 0, n = this->getEltCount(); i < n; ++i) {
1432 CapabilityElt const &elt = this->elt(i);
1433 switch (elt.getCapType()) {
1434 case CapabilityElt::PACKET_FORWARD_METHOD:
1435 x = elt.getCapData();
1436 if (0 < x && x < 4)
1437 m_packet_forward = static_cast<ServiceGroup::PacketStyle>(x);
1438 break;
1439 case CapabilityElt::PACKET_RETURN_METHOD:
1440 x = elt.getCapData();
1441 if (0 < x && x < 4)
1442 m_packet_return = static_cast<ServiceGroup::PacketStyle>(x);
1443 break;
1444 case CapabilityElt::CACHE_ASSIGNMENT_METHOD:
1445 x = elt.getCapData();
1446 if (0 < x && x < 4)
1447 m_cache_assign = static_cast<ServiceGroup::CacheAssignmentStyle>(x);
1448 break;
1449 default:
1450 logf(LVL_INFO, "Invalid capability type %d in packet.", elt.getCapType());
1451 break;
1452 }
1453 }
1454 m_cached = true;
1455 }
1456
1457 CapComp &
fill(MsgBuffer & buffer,int n)1458 CapComp::fill(MsgBuffer &buffer, int n)
1459 {
1460 size_t comp_size = this->calcSize(n);
1461 m_cached = false;
1462
1463 if (buffer.getSpace() < comp_size)
1464 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
1465
1466 m_base = buffer.getTail();
1467 this->setType(COMP_TYPE).setLength(comp_size - sizeof(super::raw_t));
1468 m_count = n;
1469 buffer.use(comp_size);
1470
1471 return *this;
1472 }
1473
1474 int
parse(MsgBuffer & buffer)1475 CapComp::parse(MsgBuffer &buffer)
1476 {
1477 int zret = PARSE_SUCCESS;
1478 m_cached = false;
1479 if (buffer.getSpace() < sizeof(raw_t))
1480 zret = PARSE_BUFFER_TOO_SMALL;
1481 else {
1482 m_base = buffer.getTail();
1483 zret = this->checkHeader(buffer, COMP_TYPE);
1484 if (PARSE_SUCCESS == zret) {
1485 // No explicit count, compute it from length.
1486 m_count = this->getLength() / sizeof(CapabilityElt);
1487 buffer.use(this->getLength() + sizeof(super::raw_t));
1488 }
1489 }
1490 return zret;
1491 }
1492 // ------------------------------------------------------
1493 int
parse(MsgBuffer & buffer)1494 QueryComp::parse(MsgBuffer &buffer)
1495 {
1496 int zret = PARSE_SUCCESS;
1497 if (buffer.getSpace() < sizeof(raw_t))
1498 zret = PARSE_BUFFER_TOO_SMALL;
1499 else {
1500 m_base = buffer.getTail();
1501 zret = this->checkHeader(buffer, COMP_TYPE);
1502 if (PARSE_SUCCESS == zret)
1503 buffer.use(this->calcSize());
1504 }
1505 return zret;
1506 }
1507 // ------------------------------------------------------
1508 uint32_t
getCount() const1509 AssignMapComp::getCount() const
1510 {
1511 return access_field(&raw_t::m_assign, m_base).getCount();
1512 }
1513
1514 AssignMapComp &
fill(MsgBuffer & buffer,detail::Assignment const & assign)1515 AssignMapComp::fill(MsgBuffer &buffer, detail::Assignment const &assign)
1516 {
1517 size_t comp_size = sizeof(raw_t);
1518 MaskAssignElt const &ma = assign.getMask();
1519 size_t ma_size = ma.getSize(); // Not constant time.
1520
1521 // Can't be precise, but we need at least one mask/value set with
1522 // at least one value. If we don't have that it's a clear fail.
1523 if (buffer.getSpace() < comp_size + sizeof(MaskValueSetElt::calcSize(1)))
1524 throw ts::Exception(BUFFER_TOO_SMALL_FOR_COMP_TEXT);
1525
1526 m_base = buffer.getTail();
1527 memcpy(&(access_field(&raw_t::m_assign, m_base)), &ma, ma_size);
1528 comp_size += ma_size - sizeof(ma);
1529
1530 this->setType(COMP_TYPE).setLength(comp_size - HEADER_SIZE);
1531 buffer.use(comp_size);
1532
1533 return *this;
1534 }
1535
1536 int
parse(MsgBuffer & buffer)1537 AssignMapComp::parse(MsgBuffer &buffer)
1538 {
1539 int zret = PARSE_SUCCESS;
1540 if (buffer.getSpace() < HEADER_SIZE)
1541 zret = PARSE_BUFFER_TOO_SMALL;
1542 else {
1543 m_base = buffer.getTail();
1544 zret = this->checkHeader(buffer, COMP_TYPE);
1545 if (PARSE_SUCCESS == zret) {
1546 // TBD - Actually check the mask/value set data !!
1547 buffer.use(this->getLength() + HEADER_SIZE);
1548 }
1549 }
1550 if (PARSE_SUCCESS != zret)
1551 m_base = 0;
1552 return zret;
1553 }
1554 // ------------------------------------------------------
Assignment()1555 detail::Assignment::Assignment() : m_key(0, 0), m_active(false), m_router_list(0), m_hash_assign(0), m_mask_assign(0) {}
1556
1557 bool
fill(cache::GroupData & group,uint32_t addr)1558 detail::Assignment::fill(cache::GroupData &group, uint32_t addr)
1559 {
1560 // Compute the last packet received times for the routers. For each
1561 // cache, compute how many routers mentioned it in their last
1562 // packet. Prepare an assignment from those caches. If there are no
1563 // such caches, fail the assignment. Any cache that wasn't
1564 // mentioned by at least one router are purged.
1565
1566 size_t n_routers = group.m_routers.size(); // routers in group
1567 size_t n_caches = group.m_caches.size(); // caches in group
1568
1569 // We need both routers and caches to do something useful.
1570 if (!(n_routers && n_caches))
1571 return false;
1572
1573 // Iteration vars.
1574 size_t cdx, rdx;
1575 cache::RouterBag::iterator rspot, rbegin = group.m_routers.begin(), rend = group.m_routers.end();
1576 cache::CacheBag::iterator cspot, cbegin = group.m_caches.begin(), cend = group.m_caches.end();
1577
1578 size_t nr[n_caches]; // validity check counts.
1579 memset(nr, 0, sizeof(nr)); // Set counts to zero.
1580
1581 // Guess at size of serialization buffer. For the router list and
1582 // the hash assignment, we can compute reasonable upper bounds and so
1583 // we don't have to do space checks when those get filled out.
1584 // The mask assignment is more difficult. We just guess generously and
1585 // try to recover if we go over.
1586 size_t size = RouterAssignListElt::calcSize(n_routers) + HashAssignElt::calcSize(n_caches) + 4096;
1587
1588 if (m_buffer.getSize() < size) {
1589 ats_free(m_buffer.getBase());
1590 m_buffer.set(ats_malloc(size), size);
1591 }
1592 m_buffer.reset();
1593
1594 // Set assignment key
1595 m_key.setAddr(addr).setChangeNumber(group.m_generation);
1596
1597 m_router_list = reinterpret_cast<RouterAssignListElt *>(m_buffer.getBase());
1598 new (m_router_list) RouterAssignListElt(n_routers);
1599
1600 // For each router, update the assignment and run over the caches
1601 // and bump the nr count if that cache was included in the most
1602 // recent packet. Note that the router data gets updated from
1603 // ISeeYou message processing as well, this is more of an initial
1604 // setup.
1605 for (rdx = 0, rspot = rbegin; rspot != rend; ++rspot, ++rdx) {
1606 // Update router assignment.
1607 m_router_list->elt(rdx).setChangeNumber(rspot->m_generation).setAddr(rspot->m_addr).setRecvId(rspot->m_recv.m_sn);
1608 // Check cache validity.
1609 for (cdx = 0, cspot = cbegin; cspot != cend; ++cspot, ++cdx) {
1610 if (cspot->m_src[rdx].m_time == rspot->m_recv.m_time)
1611 ++(nr[cdx]);
1612 }
1613 }
1614
1615 size_t k = m_router_list->getSize();
1616 m_buffer.use(k);
1617 m_hash_assign = reinterpret_cast<HashAssignElt *>(m_buffer.getTail());
1618
1619 // If the nr value is 0, then the cache was not included in any
1620 // last packet, so it should be discarded. A cache is valid if
1621 // nr is n_routers, indicating that every router mentioned it.
1622 int v_caches = 0; // valid caches
1623 for (cdx = 0, cspot = cbegin; cspot != cend; ++cspot, ++cdx)
1624 if (nr[cdx] == n_routers) {
1625 m_hash_assign->setAddr(cdx, cspot->idAddr());
1626 ++v_caches;
1627 }
1628
1629 if (!v_caches) { // no valid caches.
1630 log(LVL_INFO, "Attempted to generate cache assignment but no valid caches were found.");
1631 return false;
1632 }
1633 // Just sets the cache count.
1634 new (m_hash_assign) HashAssignElt(v_caches);
1635 m_hash_assign->round_robin_assign();
1636 m_buffer.use(m_hash_assign->getSize());
1637
1638 m_mask_assign = reinterpret_cast<MaskAssignElt *>(m_buffer.getTail());
1639 new (m_mask_assign) MaskAssignElt;
1640
1641 // For now, hardwire everything to first cache.
1642 // We have plenty of space, but will need to check if we do something
1643 // more complex here.
1644 m_mask_assign->init(0, 0, 0, 0)->addValue(m_hash_assign->getAddr(0), 0, 0, 0, 0);
1645
1646 logf(LVL_INFO, "Generated assignment for group %d with %d routers, %d valid caches.", group.m_svc.getSvcId(), n_routers,
1647 v_caches);
1648
1649 return true;
1650 }
1651 // ------------------------------------------------------
1652 void
setBuffer(MsgBuffer const & buffer)1653 BaseMsg::setBuffer(MsgBuffer const &buffer)
1654 {
1655 m_buffer = buffer;
1656 }
1657
1658 void
finalize()1659 BaseMsg::finalize()
1660 {
1661 m_header.setLength(m_buffer.getCount() - m_header.calcSize());
1662 m_security.secure(m_buffer);
1663 }
1664
1665 bool
validateSecurity() const1666 BaseMsg::validateSecurity() const
1667 {
1668 return m_security.validate(m_buffer);
1669 }
1670 // ------------------------------------------------------
1671 void
fill(detail::cache::GroupData const & group,CacheIdBox const & cache_id,SecurityOption sec_opt)1672 HereIAmMsg::fill(detail::cache::GroupData const &group, CacheIdBox const &cache_id, SecurityOption sec_opt)
1673 {
1674 m_header.fill(m_buffer, HERE_I_AM);
1675 m_security.fill(m_buffer, sec_opt);
1676 m_service.fill(m_buffer, group.m_svc);
1677 m_cache_id.fill(m_buffer, cache_id);
1678 m_cache_view.fill(m_buffer, group);
1679 }
1680
1681 void
fill_caps(detail::cache::RouterData const & router)1682 HereIAmMsg::fill_caps(detail::cache::RouterData const &router)
1683 {
1684 if (router.m_send_caps) {
1685 m_capabilities.fill(m_buffer, 3);
1686 m_capabilities.elt(0) = CapabilityElt(CapabilityElt::PACKET_FORWARD_METHOD, router.m_packet_forward);
1687 m_capabilities.elt(1) = CapabilityElt(CapabilityElt::CACHE_ASSIGNMENT_METHOD, router.m_cache_assign);
1688 m_capabilities.elt(2) = CapabilityElt(CapabilityElt::PACKET_RETURN_METHOD, router.m_packet_return);
1689 }
1690 }
1691
1692 int
parse(ts::Buffer const & buffer)1693 HereIAmMsg::parse(ts::Buffer const &buffer)
1694 {
1695 int zret;
1696 this->setBuffer(buffer);
1697 if (!m_buffer.getBase())
1698 return -EINVAL;
1699 zret = m_header.parse(m_buffer);
1700 if (PARSE_SUCCESS != zret)
1701 return zret;
1702 if (HERE_I_AM != m_header.getType())
1703 return PARSE_MSG_WRONG_TYPE;
1704
1705 // Time to look for components.
1706 zret = m_security.parse(m_buffer);
1707 if (PARSE_SUCCESS != zret)
1708 return zret;
1709
1710 zret = m_service.parse(m_buffer);
1711 if (PARSE_SUCCESS != zret)
1712 return zret;
1713
1714 zret = m_cache_id.parse(m_buffer);
1715 if (PARSE_SUCCESS != zret)
1716 return zret;
1717
1718 zret = m_cache_view.parse(m_buffer);
1719 if (PARSE_SUCCESS != zret)
1720 return zret;
1721
1722 // These are optional so failures can be ignored.
1723 if (m_buffer.getSpace())
1724 m_capabilities.parse(m_buffer);
1725 if (m_buffer.getSpace())
1726 m_command.parse(m_buffer);
1727
1728 return m_buffer.getSpace() ? PARSE_DATA_OVERRUN : PARSE_SUCCESS;
1729 }
1730 // ------------------------------------------------------
1731 void
fill(detail::cache::GroupData const & group,SecurityOption sec_opt)1732 RedirectAssignMsg::fill(detail::cache::GroupData const &group, SecurityOption sec_opt)
1733 {
1734 m_header.fill(m_buffer, REDIRECT_ASSIGN);
1735 m_security.fill(m_buffer, sec_opt);
1736 m_service.fill(m_buffer, group.m_svc);
1737 switch (group.m_cache_assign) {
1738 case ServiceGroup::HASH_ONLY:
1739 m_hash_assign.fill(m_buffer, group.m_assign_info);
1740 break;
1741 case ServiceGroup::MASK_ONLY:
1742 m_alt_mask_assign.fill(m_buffer, group.m_assign_info);
1743 break;
1744 default:
1745 logf(LVL_WARN, "Bad assignment type [%d] for REDIRECT_ASSIGN", group.m_cache_assign);
1746 break;
1747 }
1748 }
1749 // ------------------------------------------------------
1750 void
fill(detail::router::GroupData const & group,SecurityOption sec_opt,detail::Assignment &,size_t to_caches,size_t n_routers,size_t n_caches,bool)1751 ISeeYouMsg::fill(detail::router::GroupData const &group, SecurityOption sec_opt, detail::Assignment & /* assign ATS_UNUSED */,
1752 size_t to_caches, size_t n_routers, size_t n_caches, bool /* send_capabilities ATS_UNUSED */
1753 )
1754 {
1755 m_header.fill(m_buffer, I_SEE_YOU);
1756 m_security.fill(m_buffer, sec_opt);
1757 m_service.fill(m_buffer, group.m_svc);
1758 m_router_id.fill(m_buffer, to_caches);
1759 m_router_view.fill(m_buffer, n_routers, n_caches);
1760 }
1761
1762 int
parse(ts::Buffer const & buffer)1763 ISeeYouMsg::parse(ts::Buffer const &buffer)
1764 {
1765 int zret;
1766 this->setBuffer(buffer);
1767 if (!m_buffer.getBase())
1768 return -EINVAL;
1769 zret = m_header.parse(m_buffer);
1770 if (PARSE_SUCCESS != zret)
1771 return zret;
1772 if (I_SEE_YOU != m_header.getType())
1773 return PARSE_MSG_WRONG_TYPE;
1774
1775 // Time to look for components.
1776 zret = m_security.parse(m_buffer);
1777 if (PARSE_SUCCESS != zret)
1778 return zret;
1779
1780 zret = m_service.parse(m_buffer);
1781 if (PARSE_SUCCESS != zret)
1782 return zret;
1783
1784 zret = m_router_id.parse(m_buffer);
1785 if (PARSE_SUCCESS != zret) {
1786 logf(LVL_DEBUG, "I_SEE_YOU: Invalid %d router id", zret);
1787 return zret;
1788 }
1789
1790 zret = m_router_view.parse(m_buffer);
1791 if (PARSE_SUCCESS != zret) {
1792 logf(LVL_DEBUG, "I_SEE_YOU: Invalid %d router view", zret);
1793 return zret;
1794 }
1795
1796 // Optional components.
1797
1798 // Test for alternates here
1799 // At most one of the assignments but never both.
1800 // Can be omitted.
1801 m_assignment.parse(m_buffer);
1802 m_map.parse(m_buffer);
1803
1804 // Optional components.
1805 m_capabilities.parse(m_buffer);
1806 m_command.parse(m_buffer);
1807
1808 if (m_buffer.getSpace()) {
1809 zret = PARSE_DATA_OVERRUN;
1810 logf(LVL_DEBUG, "I_SEE_YOU: Data overrun %lu", m_buffer.getSpace());
1811 }
1812
1813 return zret;
1814 }
1815 // ------------------------------------------------------
1816 int
parse(ts::Buffer const & buffer)1817 RemovalQueryMsg::parse(ts::Buffer const &buffer)
1818 {
1819 int zret;
1820 this->setBuffer(buffer);
1821 if (!m_buffer.getBase())
1822 return -EINVAL;
1823 zret = m_header.parse(m_buffer);
1824 if (PARSE_SUCCESS != zret)
1825 return zret;
1826 if (REMOVAL_QUERY != m_header.getType())
1827 return PARSE_MSG_WRONG_TYPE;
1828
1829 // Get the components.
1830 zret = m_security.parse(m_buffer);
1831 if (PARSE_SUCCESS != zret)
1832 return zret;
1833
1834 zret = m_service.parse(m_buffer);
1835 if (PARSE_SUCCESS != zret)
1836 return zret;
1837
1838 zret = m_query.parse(m_buffer);
1839 if (PARSE_SUCCESS != zret)
1840 return zret;
1841
1842 return m_buffer.getSpace() ? PARSE_DATA_OVERRUN : PARSE_SUCCESS;
1843 }
1844 // ------------------------------------------------------
1845 } // namespace wccp
1846