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