github.com/sagernet/netlink@v0.0.0-20240612041022-b9a21c07ac6a/filter_linux.go (about) 1 package netlink 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "encoding/hex" 7 "errors" 8 "fmt" 9 "net" 10 "syscall" 11 12 "github.com/sagernet/netlink/nl" 13 "golang.org/x/sys/unix" 14 ) 15 16 // Constants used in TcU32Sel.Flags. 17 const ( 18 TC_U32_TERMINAL = nl.TC_U32_TERMINAL 19 TC_U32_OFFSET = nl.TC_U32_OFFSET 20 TC_U32_VAROFFSET = nl.TC_U32_VAROFFSET 21 TC_U32_EAT = nl.TC_U32_EAT 22 ) 23 24 // Sel of the U32 filters that contains multiple TcU32Key. This is the type 25 // alias and the frontend representation of nl.TcU32Sel. It is serialized into 26 // canonical nl.TcU32Sel with the appropriate endianness. 27 type TcU32Sel = nl.TcU32Sel 28 29 // TcU32Key contained of Sel in the U32 filters. This is the type alias and the 30 // frontend representation of nl.TcU32Key. It is serialized into chanonical 31 // nl.TcU32Sel with the appropriate endianness. 32 type TcU32Key = nl.TcU32Key 33 34 // U32 filters on many packet related properties 35 type U32 struct { 36 FilterAttrs 37 ClassId uint32 38 Divisor uint32 // Divisor MUST be power of 2. 39 Hash uint32 40 Link uint32 41 RedirIndex int 42 Sel *TcU32Sel 43 Actions []Action 44 } 45 46 func (filter *U32) Attrs() *FilterAttrs { 47 return &filter.FilterAttrs 48 } 49 50 func (filter *U32) Type() string { 51 return "u32" 52 } 53 54 type Flower struct { 55 FilterAttrs 56 DestIP net.IP 57 DestIPMask net.IPMask 58 SrcIP net.IP 59 SrcIPMask net.IPMask 60 EthType uint16 61 EncDestIP net.IP 62 EncDestIPMask net.IPMask 63 EncSrcIP net.IP 64 EncSrcIPMask net.IPMask 65 EncDestPort uint16 66 EncKeyId uint32 67 68 Actions []Action 69 } 70 71 func (filter *Flower) Attrs() *FilterAttrs { 72 return &filter.FilterAttrs 73 } 74 75 func (filter *Flower) Type() string { 76 return "flower" 77 } 78 79 func (filter *Flower) encodeIP(parent *nl.RtAttr, ip net.IP, mask net.IPMask, v4Type, v6Type int, v4MaskType, v6MaskType int) { 80 ipType := v4Type 81 maskType := v4MaskType 82 83 encodeMask := mask 84 if mask == nil { 85 encodeMask = net.CIDRMask(32, 32) 86 } 87 v4IP := ip.To4() 88 if v4IP == nil { 89 ipType = v6Type 90 maskType = v6MaskType 91 if mask == nil { 92 encodeMask = net.CIDRMask(128, 128) 93 } 94 } else { 95 ip = v4IP 96 } 97 98 parent.AddRtAttr(ipType, ip) 99 parent.AddRtAttr(maskType, encodeMask) 100 } 101 102 func (filter *Flower) encode(parent *nl.RtAttr) error { 103 if filter.EthType != 0 { 104 parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_TYPE, htons(filter.EthType)) 105 } 106 if filter.SrcIP != nil { 107 filter.encodeIP(parent, filter.SrcIP, filter.SrcIPMask, 108 nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC, 109 nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK) 110 } 111 if filter.DestIP != nil { 112 filter.encodeIP(parent, filter.DestIP, filter.DestIPMask, 113 nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST, 114 nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK) 115 } 116 if filter.EncSrcIP != nil { 117 filter.encodeIP(parent, filter.EncSrcIP, filter.EncSrcIPMask, 118 nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC, 119 nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK) 120 } 121 if filter.EncDestIP != nil { 122 filter.encodeIP(parent, filter.EncDestIP, filter.EncSrcIPMask, 123 nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST, 124 nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK) 125 } 126 if filter.EncDestPort != 0 { 127 parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT, htons(filter.EncDestPort)) 128 } 129 if filter.EncKeyId != 0 { 130 parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId)) 131 } 132 133 actionsAttr := parent.AddRtAttr(nl.TCA_FLOWER_ACT, nil) 134 if err := EncodeActions(actionsAttr, filter.Actions); err != nil { 135 return err 136 } 137 return nil 138 } 139 140 func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error { 141 for _, datum := range data { 142 switch datum.Attr.Type { 143 case nl.TCA_FLOWER_KEY_ETH_TYPE: 144 filter.EthType = ntohs(datum.Value) 145 case nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC: 146 filter.SrcIP = datum.Value 147 case nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK: 148 filter.SrcIPMask = datum.Value 149 case nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST: 150 filter.DestIP = datum.Value 151 case nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK: 152 filter.DestIPMask = datum.Value 153 case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC: 154 filter.EncSrcIP = datum.Value 155 case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK: 156 filter.EncSrcIPMask = datum.Value 157 case nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST: 158 filter.EncDestIP = datum.Value 159 case nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK: 160 filter.EncDestIPMask = datum.Value 161 case nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT: 162 filter.EncDestPort = ntohs(datum.Value) 163 case nl.TCA_FLOWER_KEY_ENC_KEY_ID: 164 filter.EncKeyId = ntohl(datum.Value) 165 case nl.TCA_FLOWER_ACT: 166 tables, err := nl.ParseRouteAttr(datum.Value) 167 if err != nil { 168 return err 169 } 170 filter.Actions, err = parseActions(tables) 171 if err != nil { 172 return err 173 } 174 } 175 } 176 return nil 177 } 178 179 // FilterDel will delete a filter from the system. 180 // Equivalent to: `tc filter del $filter` 181 func FilterDel(filter Filter) error { 182 return pkgHandle.FilterDel(filter) 183 } 184 185 // FilterDel will delete a filter from the system. 186 // Equivalent to: `tc filter del $filter` 187 func (h *Handle) FilterDel(filter Filter) error { 188 req := h.newNetlinkRequest(unix.RTM_DELTFILTER, unix.NLM_F_ACK) 189 base := filter.Attrs() 190 msg := &nl.TcMsg{ 191 Family: nl.FAMILY_ALL, 192 Ifindex: int32(base.LinkIndex), 193 Handle: base.Handle, 194 Parent: base.Parent, 195 Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)), 196 } 197 req.AddData(msg) 198 199 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 200 return err 201 } 202 203 // FilterAdd will add a filter to the system. 204 // Equivalent to: `tc filter add $filter` 205 func FilterAdd(filter Filter) error { 206 return pkgHandle.FilterAdd(filter) 207 } 208 209 // FilterAdd will add a filter to the system. 210 // Equivalent to: `tc filter add $filter` 211 func (h *Handle) FilterAdd(filter Filter) error { 212 return h.filterModify(filter, unix.NLM_F_CREATE|unix.NLM_F_EXCL) 213 } 214 215 // FilterReplace will replace a filter. 216 // Equivalent to: `tc filter replace $filter` 217 func FilterReplace(filter Filter) error { 218 return pkgHandle.FilterReplace(filter) 219 } 220 221 // FilterReplace will replace a filter. 222 // Equivalent to: `tc filter replace $filter` 223 func (h *Handle) FilterReplace(filter Filter) error { 224 return h.filterModify(filter, unix.NLM_F_CREATE) 225 } 226 227 func (h *Handle) filterModify(filter Filter, flags int) error { 228 req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK) 229 base := filter.Attrs() 230 msg := &nl.TcMsg{ 231 Family: nl.FAMILY_ALL, 232 Ifindex: int32(base.LinkIndex), 233 Handle: base.Handle, 234 Parent: base.Parent, 235 Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)), 236 } 237 req.AddData(msg) 238 req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type()))) 239 240 options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) 241 242 switch filter := filter.(type) { 243 case *U32: 244 sel := filter.Sel 245 if sel == nil { 246 // match all 247 sel = &nl.TcU32Sel{ 248 Nkeys: 1, 249 Flags: nl.TC_U32_TERMINAL, 250 } 251 sel.Keys = append(sel.Keys, nl.TcU32Key{}) 252 } 253 254 if native != networkOrder { 255 // Copy TcU32Sel. 256 cSel := *sel 257 keys := make([]nl.TcU32Key, cap(sel.Keys)) 258 copy(keys, sel.Keys) 259 cSel.Keys = keys 260 sel = &cSel 261 262 // Handle the endianness of attributes 263 sel.Offmask = native.Uint16(htons(sel.Offmask)) 264 sel.Hmask = native.Uint32(htonl(sel.Hmask)) 265 for i, key := range sel.Keys { 266 sel.Keys[i].Mask = native.Uint32(htonl(key.Mask)) 267 sel.Keys[i].Val = native.Uint32(htonl(key.Val)) 268 } 269 } 270 sel.Nkeys = uint8(len(sel.Keys)) 271 options.AddRtAttr(nl.TCA_U32_SEL, sel.Serialize()) 272 if filter.ClassId != 0 { 273 options.AddRtAttr(nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId)) 274 } 275 if filter.Divisor != 0 { 276 if (filter.Divisor-1)&filter.Divisor != 0 { 277 return fmt.Errorf("illegal divisor %d. Must be a power of 2", filter.Divisor) 278 } 279 options.AddRtAttr(nl.TCA_U32_DIVISOR, nl.Uint32Attr(filter.Divisor)) 280 } 281 if filter.Hash != 0 { 282 options.AddRtAttr(nl.TCA_U32_HASH, nl.Uint32Attr(filter.Hash)) 283 } 284 if filter.Link != 0 { 285 options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link)) 286 } 287 actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil) 288 // backwards compatibility 289 if filter.RedirIndex != 0 { 290 filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...) 291 } 292 if err := EncodeActions(actionsAttr, filter.Actions); err != nil { 293 return err 294 } 295 case *FwFilter: 296 if filter.Mask != 0 { 297 b := make([]byte, 4) 298 native.PutUint32(b, filter.Mask) 299 options.AddRtAttr(nl.TCA_FW_MASK, b) 300 } 301 if filter.InDev != "" { 302 options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev)) 303 } 304 if filter.Police != nil { 305 police := options.AddRtAttr(nl.TCA_FW_POLICE, nil) 306 if err := encodePolice(police, filter.Police); err != nil { 307 return err 308 } 309 } 310 if filter.ClassId != 0 { 311 b := make([]byte, 4) 312 native.PutUint32(b, filter.ClassId) 313 options.AddRtAttr(nl.TCA_FW_CLASSID, b) 314 } 315 case *BpfFilter: 316 var bpfFlags uint32 317 if filter.ClassId != 0 { 318 options.AddRtAttr(nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId)) 319 } 320 if filter.Fd >= 0 { 321 options.AddRtAttr(nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd)))) 322 } 323 if filter.Name != "" { 324 options.AddRtAttr(nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name)) 325 } 326 if filter.DirectAction { 327 bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT 328 } 329 options.AddRtAttr(nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags)) 330 case *MatchAll: 331 actionsAttr := options.AddRtAttr(nl.TCA_MATCHALL_ACT, nil) 332 if err := EncodeActions(actionsAttr, filter.Actions); err != nil { 333 return err 334 } 335 if filter.ClassId != 0 { 336 options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId)) 337 } 338 case *Flower: 339 if err := filter.encode(options); err != nil { 340 return err 341 } 342 } 343 344 req.AddData(options) 345 _, err := req.Execute(unix.NETLINK_ROUTE, 0) 346 return err 347 } 348 349 // FilterList gets a list of filters in the system. 350 // Equivalent to: `tc filter show`. 351 // Generally returns nothing if link and parent are not specified. 352 func FilterList(link Link, parent uint32) ([]Filter, error) { 353 return pkgHandle.FilterList(link, parent) 354 } 355 356 // FilterList gets a list of filters in the system. 357 // Equivalent to: `tc filter show`. 358 // Generally returns nothing if link and parent are not specified. 359 func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { 360 req := h.newNetlinkRequest(unix.RTM_GETTFILTER, unix.NLM_F_DUMP) 361 msg := &nl.TcMsg{ 362 Family: nl.FAMILY_ALL, 363 Parent: parent, 364 } 365 if link != nil { 366 base := link.Attrs() 367 h.ensureIndex(base) 368 msg.Ifindex = int32(base.Index) 369 } 370 req.AddData(msg) 371 372 msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER) 373 if err != nil { 374 return nil, err 375 } 376 377 var res []Filter 378 for _, m := range msgs { 379 msg := nl.DeserializeTcMsg(m) 380 381 attrs, err := nl.ParseRouteAttr(m[msg.Len():]) 382 if err != nil { 383 return nil, err 384 } 385 386 base := FilterAttrs{ 387 LinkIndex: int(msg.Ifindex), 388 Handle: msg.Handle, 389 Parent: msg.Parent, 390 } 391 base.Priority, base.Protocol = MajorMinor(msg.Info) 392 base.Protocol = nl.Swap16(base.Protocol) 393 394 var filter Filter 395 filterType := "" 396 detailed := false 397 for _, attr := range attrs { 398 switch attr.Attr.Type { 399 case nl.TCA_KIND: 400 filterType = string(attr.Value[:len(attr.Value)-1]) 401 switch filterType { 402 case "u32": 403 filter = &U32{} 404 case "fw": 405 filter = &FwFilter{} 406 case "bpf": 407 filter = &BpfFilter{} 408 case "matchall": 409 filter = &MatchAll{} 410 case "flower": 411 filter = &Flower{} 412 default: 413 filter = &GenericFilter{FilterType: filterType} 414 } 415 case nl.TCA_OPTIONS: 416 data, err := nl.ParseRouteAttr(attr.Value) 417 if err != nil { 418 return nil, err 419 } 420 switch filterType { 421 case "u32": 422 detailed, err = parseU32Data(filter, data) 423 if err != nil { 424 return nil, err 425 } 426 case "fw": 427 detailed, err = parseFwData(filter, data) 428 if err != nil { 429 return nil, err 430 } 431 case "bpf": 432 detailed, err = parseBpfData(filter, data) 433 if err != nil { 434 return nil, err 435 } 436 case "matchall": 437 detailed, err = parseMatchAllData(filter, data) 438 if err != nil { 439 return nil, err 440 } 441 case "flower": 442 detailed, err = parseFlowerData(filter, data) 443 if err != nil { 444 return nil, err 445 } 446 default: 447 detailed = true 448 } 449 } 450 } 451 // only return the detailed version of the filter 452 if detailed { 453 *filter.Attrs() = base 454 res = append(res, filter) 455 } 456 } 457 458 return res, nil 459 } 460 461 func toTcGen(attrs *ActionAttrs, tcgen *nl.TcGen) { 462 tcgen.Index = uint32(attrs.Index) 463 tcgen.Capab = uint32(attrs.Capab) 464 tcgen.Action = int32(attrs.Action) 465 tcgen.Refcnt = int32(attrs.Refcnt) 466 tcgen.Bindcnt = int32(attrs.Bindcnt) 467 } 468 469 func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) { 470 attrs.Index = int(tcgen.Index) 471 attrs.Capab = int(tcgen.Capab) 472 attrs.Action = TcAct(tcgen.Action) 473 attrs.Refcnt = int(tcgen.Refcnt) 474 attrs.Bindcnt = int(tcgen.Bindcnt) 475 } 476 477 func encodePolice(attr *nl.RtAttr, action *PoliceAction) error { 478 var rtab [256]uint32 479 var ptab [256]uint32 480 police := nl.TcPolice{} 481 police.Index = uint32(action.Attrs().Index) 482 police.Bindcnt = int32(action.Attrs().Bindcnt) 483 police.Capab = uint32(action.Attrs().Capab) 484 police.Refcnt = int32(action.Attrs().Refcnt) 485 police.Rate.Rate = action.Rate 486 police.PeakRate.Rate = action.PeakRate 487 police.Action = int32(action.ExceedAction) 488 489 if police.Rate.Rate != 0 { 490 police.Rate.Mpu = action.Mpu 491 police.Rate.Overhead = action.Overhead 492 if CalcRtable(&police.Rate, rtab[:], action.RCellLog, action.Mtu, action.LinkLayer) < 0 { 493 return errors.New("TBF: failed to calculate rate table") 494 } 495 police.Burst = Xmittime(uint64(police.Rate.Rate), action.Burst) 496 } 497 498 police.Mtu = action.Mtu 499 if police.PeakRate.Rate != 0 { 500 police.PeakRate.Mpu = action.Mpu 501 police.PeakRate.Overhead = action.Overhead 502 if CalcRtable(&police.PeakRate, ptab[:], action.PCellLog, action.Mtu, action.LinkLayer) < 0 { 503 return errors.New("POLICE: failed to calculate peak rate table") 504 } 505 } 506 507 attr.AddRtAttr(nl.TCA_POLICE_TBF, police.Serialize()) 508 if police.Rate.Rate != 0 { 509 attr.AddRtAttr(nl.TCA_POLICE_RATE, SerializeRtab(rtab)) 510 } 511 if police.PeakRate.Rate != 0 { 512 attr.AddRtAttr(nl.TCA_POLICE_PEAKRATE, SerializeRtab(ptab)) 513 } 514 if action.AvRate != 0 { 515 attr.AddRtAttr(nl.TCA_POLICE_AVRATE, nl.Uint32Attr(action.AvRate)) 516 } 517 if action.NotExceedAction != 0 { 518 attr.AddRtAttr(nl.TCA_POLICE_RESULT, nl.Uint32Attr(uint32(action.NotExceedAction))) 519 } 520 521 return nil 522 } 523 524 func EncodeActions(attr *nl.RtAttr, actions []Action) error { 525 tabIndex := int(nl.TCA_ACT_TAB) 526 527 for _, action := range actions { 528 switch action := action.(type) { 529 default: 530 return fmt.Errorf("unknown action type %s", action.Type()) 531 case *PoliceAction: 532 table := attr.AddRtAttr(tabIndex, nil) 533 tabIndex++ 534 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("police")) 535 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) 536 if err := encodePolice(aopts, action); err != nil { 537 return err 538 } 539 case *MirredAction: 540 table := attr.AddRtAttr(tabIndex, nil) 541 tabIndex++ 542 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred")) 543 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) 544 mirred := nl.TcMirred{ 545 Eaction: int32(action.MirredAction), 546 Ifindex: uint32(action.Ifindex), 547 } 548 toTcGen(action.Attrs(), &mirred.TcGen) 549 aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize()) 550 case *TunnelKeyAction: 551 table := attr.AddRtAttr(tabIndex, nil) 552 tabIndex++ 553 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("tunnel_key")) 554 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) 555 tun := nl.TcTunnelKey{ 556 Action: int32(action.Action), 557 } 558 toTcGen(action.Attrs(), &tun.TcGen) 559 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_PARMS, tun.Serialize()) 560 if action.Action == TCA_TUNNEL_KEY_SET { 561 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_KEY_ID, htonl(action.KeyID)) 562 if v4 := action.SrcAddr.To4(); v4 != nil { 563 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC, v4[:]) 564 } else if v6 := action.SrcAddr.To16(); v6 != nil { 565 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, v6[:]) 566 } else { 567 return fmt.Errorf("invalid src addr %s for tunnel_key action", action.SrcAddr) 568 } 569 if v4 := action.DstAddr.To4(); v4 != nil { 570 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_DST, v4[:]) 571 } else if v6 := action.DstAddr.To16(); v6 != nil { 572 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, v6[:]) 573 } else { 574 return fmt.Errorf("invalid dst addr %s for tunnel_key action", action.DstAddr) 575 } 576 if action.DestPort != 0 { 577 aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_DST_PORT, htons(action.DestPort)) 578 } 579 } 580 case *SkbEditAction: 581 table := attr.AddRtAttr(tabIndex, nil) 582 tabIndex++ 583 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("skbedit")) 584 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) 585 skbedit := nl.TcSkbEdit{} 586 toTcGen(action.Attrs(), &skbedit.TcGen) 587 aopts.AddRtAttr(nl.TCA_SKBEDIT_PARMS, skbedit.Serialize()) 588 if action.QueueMapping != nil { 589 aopts.AddRtAttr(nl.TCA_SKBEDIT_QUEUE_MAPPING, nl.Uint16Attr(*action.QueueMapping)) 590 } 591 if action.Priority != nil { 592 aopts.AddRtAttr(nl.TCA_SKBEDIT_PRIORITY, nl.Uint32Attr(*action.Priority)) 593 } 594 if action.PType != nil { 595 aopts.AddRtAttr(nl.TCA_SKBEDIT_PTYPE, nl.Uint16Attr(*action.PType)) 596 } 597 if action.Mark != nil { 598 aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark)) 599 } 600 case *ConnmarkAction: 601 table := attr.AddRtAttr(tabIndex, nil) 602 tabIndex++ 603 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("connmark")) 604 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) 605 connmark := nl.TcConnmark{ 606 Zone: action.Zone, 607 } 608 toTcGen(action.Attrs(), &connmark.TcGen) 609 aopts.AddRtAttr(nl.TCA_CONNMARK_PARMS, connmark.Serialize()) 610 case *CsumAction: 611 table := attr.AddRtAttr(tabIndex, nil) 612 tabIndex++ 613 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("csum")) 614 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) 615 csum := nl.TcCsum{ 616 UpdateFlags: uint32(action.UpdateFlags), 617 } 618 toTcGen(action.Attrs(), &csum.TcGen) 619 aopts.AddRtAttr(nl.TCA_CSUM_PARMS, csum.Serialize()) 620 case *BpfAction: 621 table := attr.AddRtAttr(tabIndex, nil) 622 tabIndex++ 623 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf")) 624 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) 625 gen := nl.TcGen{} 626 toTcGen(action.Attrs(), &gen) 627 aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize()) 628 aopts.AddRtAttr(nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd))) 629 aopts.AddRtAttr(nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name)) 630 case *GenericAction: 631 table := attr.AddRtAttr(tabIndex, nil) 632 tabIndex++ 633 table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("gact")) 634 aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) 635 gen := nl.TcGen{} 636 toTcGen(action.Attrs(), &gen) 637 aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize()) 638 } 639 } 640 return nil 641 } 642 643 func parsePolice(data syscall.NetlinkRouteAttr, police *PoliceAction) { 644 switch data.Attr.Type { 645 case nl.TCA_POLICE_RESULT: 646 police.NotExceedAction = TcPolAct(native.Uint32(data.Value[0:4])) 647 case nl.TCA_POLICE_AVRATE: 648 police.AvRate = native.Uint32(data.Value[0:4]) 649 case nl.TCA_POLICE_TBF: 650 p := *nl.DeserializeTcPolice(data.Value) 651 police.ActionAttrs = ActionAttrs{} 652 police.Attrs().Index = int(p.Index) 653 police.Attrs().Bindcnt = int(p.Bindcnt) 654 police.Attrs().Capab = int(p.Capab) 655 police.Attrs().Refcnt = int(p.Refcnt) 656 police.ExceedAction = TcPolAct(p.Action) 657 police.Rate = p.Rate.Rate 658 police.PeakRate = p.PeakRate.Rate 659 police.Burst = Xmitsize(uint64(p.Rate.Rate), p.Burst) 660 police.Mtu = p.Mtu 661 police.LinkLayer = int(p.Rate.Linklayer) & nl.TC_LINKLAYER_MASK 662 police.Overhead = p.Rate.Overhead 663 } 664 } 665 666 func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { 667 var actions []Action 668 for _, table := range tables { 669 var action Action 670 var actionType string 671 aattrs, err := nl.ParseRouteAttr(table.Value) 672 if err != nil { 673 return nil, err 674 } 675 nextattr: 676 for _, aattr := range aattrs { 677 switch aattr.Attr.Type { 678 case nl.TCA_KIND: 679 actionType = string(aattr.Value[:len(aattr.Value)-1]) 680 // only parse if the action is mirred or bpf 681 switch actionType { 682 case "mirred": 683 action = &MirredAction{} 684 case "bpf": 685 action = &BpfAction{} 686 case "connmark": 687 action = &ConnmarkAction{} 688 case "csum": 689 action = &CsumAction{} 690 case "gact": 691 action = &GenericAction{} 692 case "tunnel_key": 693 action = &TunnelKeyAction{} 694 case "skbedit": 695 action = &SkbEditAction{} 696 case "police": 697 action = &PoliceAction{} 698 default: 699 break nextattr 700 } 701 case nl.TCA_OPTIONS: 702 adata, err := nl.ParseRouteAttr(aattr.Value) 703 if err != nil { 704 return nil, err 705 } 706 for _, adatum := range adata { 707 switch actionType { 708 case "mirred": 709 switch adatum.Attr.Type { 710 case nl.TCA_MIRRED_PARMS: 711 mirred := *nl.DeserializeTcMirred(adatum.Value) 712 action.(*MirredAction).ActionAttrs = ActionAttrs{} 713 toAttrs(&mirred.TcGen, action.Attrs()) 714 action.(*MirredAction).Ifindex = int(mirred.Ifindex) 715 action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction) 716 } 717 case "tunnel_key": 718 switch adatum.Attr.Type { 719 case nl.TCA_TUNNEL_KEY_PARMS: 720 tun := *nl.DeserializeTunnelKey(adatum.Value) 721 action.(*TunnelKeyAction).ActionAttrs = ActionAttrs{} 722 toAttrs(&tun.TcGen, action.Attrs()) 723 action.(*TunnelKeyAction).Action = TunnelKeyAct(tun.Action) 724 case nl.TCA_TUNNEL_KEY_ENC_KEY_ID: 725 action.(*TunnelKeyAction).KeyID = networkOrder.Uint32(adatum.Value[0:4]) 726 case nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC: 727 action.(*TunnelKeyAction).SrcAddr = adatum.Value[:] 728 case nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, nl.TCA_TUNNEL_KEY_ENC_IPV4_DST: 729 action.(*TunnelKeyAction).DstAddr = adatum.Value[:] 730 case nl.TCA_TUNNEL_KEY_ENC_DST_PORT: 731 action.(*TunnelKeyAction).DestPort = ntohs(adatum.Value) 732 } 733 case "skbedit": 734 switch adatum.Attr.Type { 735 case nl.TCA_SKBEDIT_PARMS: 736 skbedit := *nl.DeserializeSkbEdit(adatum.Value) 737 action.(*SkbEditAction).ActionAttrs = ActionAttrs{} 738 toAttrs(&skbedit.TcGen, action.Attrs()) 739 case nl.TCA_SKBEDIT_MARK: 740 mark := native.Uint32(adatum.Value[0:4]) 741 action.(*SkbEditAction).Mark = &mark 742 case nl.TCA_SKBEDIT_PRIORITY: 743 priority := native.Uint32(adatum.Value[0:4]) 744 action.(*SkbEditAction).Priority = &priority 745 case nl.TCA_SKBEDIT_PTYPE: 746 ptype := native.Uint16(adatum.Value[0:2]) 747 action.(*SkbEditAction).PType = &ptype 748 case nl.TCA_SKBEDIT_QUEUE_MAPPING: 749 mapping := native.Uint16(adatum.Value[0:2]) 750 action.(*SkbEditAction).QueueMapping = &mapping 751 } 752 case "bpf": 753 switch adatum.Attr.Type { 754 case nl.TCA_ACT_BPF_PARMS: 755 gen := *nl.DeserializeTcGen(adatum.Value) 756 toAttrs(&gen, action.Attrs()) 757 case nl.TCA_ACT_BPF_FD: 758 action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4])) 759 case nl.TCA_ACT_BPF_NAME: 760 action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1]) 761 } 762 case "connmark": 763 switch adatum.Attr.Type { 764 case nl.TCA_CONNMARK_PARMS: 765 connmark := *nl.DeserializeTcConnmark(adatum.Value) 766 action.(*ConnmarkAction).ActionAttrs = ActionAttrs{} 767 toAttrs(&connmark.TcGen, action.Attrs()) 768 action.(*ConnmarkAction).Zone = connmark.Zone 769 } 770 case "csum": 771 switch adatum.Attr.Type { 772 case nl.TCA_CSUM_PARMS: 773 csum := *nl.DeserializeTcCsum(adatum.Value) 774 action.(*CsumAction).ActionAttrs = ActionAttrs{} 775 toAttrs(&csum.TcGen, action.Attrs()) 776 action.(*CsumAction).UpdateFlags = CsumUpdateFlags(csum.UpdateFlags) 777 } 778 case "gact": 779 switch adatum.Attr.Type { 780 case nl.TCA_GACT_PARMS: 781 gen := *nl.DeserializeTcGen(adatum.Value) 782 toAttrs(&gen, action.Attrs()) 783 } 784 case "police": 785 parsePolice(adatum, action.(*PoliceAction)) 786 } 787 } 788 } 789 } 790 actions = append(actions, action) 791 } 792 return actions, nil 793 } 794 795 func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { 796 u32 := filter.(*U32) 797 detailed := false 798 for _, datum := range data { 799 switch datum.Attr.Type { 800 case nl.TCA_U32_SEL: 801 detailed = true 802 sel := nl.DeserializeTcU32Sel(datum.Value) 803 u32.Sel = sel 804 if native != networkOrder { 805 // Handle the endianness of attributes 806 u32.Sel.Offmask = native.Uint16(htons(sel.Offmask)) 807 u32.Sel.Hmask = native.Uint32(htonl(sel.Hmask)) 808 for i, key := range u32.Sel.Keys { 809 u32.Sel.Keys[i].Mask = native.Uint32(htonl(key.Mask)) 810 u32.Sel.Keys[i].Val = native.Uint32(htonl(key.Val)) 811 } 812 } 813 case nl.TCA_U32_ACT: 814 tables, err := nl.ParseRouteAttr(datum.Value) 815 if err != nil { 816 return detailed, err 817 } 818 u32.Actions, err = parseActions(tables) 819 if err != nil { 820 return detailed, err 821 } 822 for _, action := range u32.Actions { 823 if action, ok := action.(*MirredAction); ok { 824 u32.RedirIndex = int(action.Ifindex) 825 } 826 } 827 case nl.TCA_U32_CLASSID: 828 u32.ClassId = native.Uint32(datum.Value) 829 case nl.TCA_U32_DIVISOR: 830 u32.Divisor = native.Uint32(datum.Value) 831 case nl.TCA_U32_HASH: 832 u32.Hash = native.Uint32(datum.Value) 833 case nl.TCA_U32_LINK: 834 u32.Link = native.Uint32(datum.Value) 835 } 836 } 837 return detailed, nil 838 } 839 840 func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { 841 fw := filter.(*FwFilter) 842 detailed := true 843 for _, datum := range data { 844 switch datum.Attr.Type { 845 case nl.TCA_FW_MASK: 846 fw.Mask = native.Uint32(datum.Value[0:4]) 847 case nl.TCA_FW_CLASSID: 848 fw.ClassId = native.Uint32(datum.Value[0:4]) 849 case nl.TCA_FW_INDEV: 850 fw.InDev = string(datum.Value[:len(datum.Value)-1]) 851 case nl.TCA_FW_POLICE: 852 var police PoliceAction 853 adata, _ := nl.ParseRouteAttr(datum.Value) 854 for _, aattr := range adata { 855 parsePolice(aattr, &police) 856 } 857 fw.Police = &police 858 } 859 } 860 return detailed, nil 861 } 862 863 func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { 864 bpf := filter.(*BpfFilter) 865 detailed := true 866 for _, datum := range data { 867 switch datum.Attr.Type { 868 case nl.TCA_BPF_FD: 869 bpf.Fd = int(native.Uint32(datum.Value[0:4])) 870 case nl.TCA_BPF_NAME: 871 bpf.Name = string(datum.Value[:len(datum.Value)-1]) 872 case nl.TCA_BPF_CLASSID: 873 bpf.ClassId = native.Uint32(datum.Value[0:4]) 874 case nl.TCA_BPF_FLAGS: 875 flags := native.Uint32(datum.Value[0:4]) 876 if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 { 877 bpf.DirectAction = true 878 } 879 case nl.TCA_BPF_ID: 880 bpf.Id = int(native.Uint32(datum.Value[0:4])) 881 case nl.TCA_BPF_TAG: 882 bpf.Tag = hex.EncodeToString(datum.Value) 883 } 884 } 885 return detailed, nil 886 } 887 888 func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { 889 matchall := filter.(*MatchAll) 890 detailed := true 891 for _, datum := range data { 892 switch datum.Attr.Type { 893 case nl.TCA_MATCHALL_CLASSID: 894 matchall.ClassId = native.Uint32(datum.Value[0:4]) 895 case nl.TCA_MATCHALL_ACT: 896 tables, err := nl.ParseRouteAttr(datum.Value) 897 if err != nil { 898 return detailed, err 899 } 900 matchall.Actions, err = parseActions(tables) 901 if err != nil { 902 return detailed, err 903 } 904 } 905 } 906 return detailed, nil 907 } 908 909 func parseFlowerData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { 910 return true, filter.(*Flower).decode(data) 911 } 912 913 func AlignToAtm(size uint) uint { 914 var linksize, cells int 915 cells = int(size / nl.ATM_CELL_PAYLOAD) 916 if (size % nl.ATM_CELL_PAYLOAD) > 0 { 917 cells++ 918 } 919 linksize = cells * nl.ATM_CELL_SIZE 920 return uint(linksize) 921 } 922 923 func AdjustSize(sz uint, mpu uint, linklayer int) uint { 924 if sz < mpu { 925 sz = mpu 926 } 927 switch linklayer { 928 case nl.LINKLAYER_ATM: 929 return AlignToAtm(sz) 930 default: 931 return sz 932 } 933 } 934 935 func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, linklayer int) int { 936 bps := rate.Rate 937 mpu := rate.Mpu 938 var sz uint 939 if mtu == 0 { 940 mtu = 2047 941 } 942 if cellLog < 0 { 943 cellLog = 0 944 for (mtu >> uint(cellLog)) > 255 { 945 cellLog++ 946 } 947 } 948 for i := 0; i < 256; i++ { 949 sz = AdjustSize(uint((i+1)<<uint32(cellLog)), uint(mpu), linklayer) 950 rtab[i] = Xmittime(uint64(bps), uint32(sz)) 951 } 952 rate.CellAlign = -1 953 rate.CellLog = uint8(cellLog) 954 rate.Linklayer = uint8(linklayer & nl.TC_LINKLAYER_MASK) 955 return cellLog 956 } 957 958 func DeserializeRtab(b []byte) [256]uint32 { 959 var rtab [256]uint32 960 r := bytes.NewReader(b) 961 _ = binary.Read(r, native, &rtab) 962 return rtab 963 } 964 965 func SerializeRtab(rtab [256]uint32) []byte { 966 var w bytes.Buffer 967 _ = binary.Write(&w, native, rtab) 968 return w.Bytes() 969 }