/* * Copyright (c) 2015 PLUMgrid, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #define PROC_KHEADERS_PATH "/sys/kernel/kheaders.tar.xz" namespace ebpf { struct FileDeleter { void operator() (FILE *fp) { fclose(fp); } }; typedef std::unique_ptr FILEPtr; // Helper with pushd/popd semantics class DirStack { public: explicit DirStack(const std::string &dst) : ok_(false) { if (getcwd(cwd_, sizeof(cwd_)) == NULL) { ::perror("getcwd"); return; } if (::chdir(dst.c_str())) { fprintf(stderr, "chdir(%s): %s\n", dst.c_str(), strerror(errno)); return; } ok_ = true; } ~DirStack() { if (!ok_) return; if (::chdir(cwd_)) { fprintf(stderr, "chdir(%s): %s\n", cwd_, strerror(errno)); } } bool ok() const { return ok_; } const char * cwd() const { return cwd_; } private: bool ok_; char cwd_[256]; }; static int ftw_cb(const char *path, const struct stat *, int, struct FTW *) { return ::remove(path); } // Scoped class to manage the creation/deletion of tmpdirs class TmpDir { public: explicit TmpDir(const std::string &prefix = "/tmp/bcc-") : ok_(false), prefix_(prefix) { prefix_ += "XXXXXX"; if (::mkdtemp((char *)prefix_.data()) == NULL) ::perror("mkdtemp"); else ok_ = true; } ~TmpDir() { if (::nftw(prefix_.c_str(), ftw_cb, 20, FTW_DEPTH) < 0) ::perror("ftw"); else ::remove(prefix_.c_str()); } bool ok() const { return ok_; } const std::string & str() const { return prefix_; } private: bool ok_; std::string prefix_; }; // Compute the kbuild flags for the currently running kernel // Do this by: // 1. Create temp Makefile with stub dummy.c // 2. Run module build on that makefile, saving the computed flags to a file // 3. Cache the file for fast flag lookup in subsequent runs // Note: Depending on environment, different cache locations may be desired. In // case we eventually support non-root user programs, cache in $HOME. class KBuildHelper { public: explicit KBuildHelper(const std::string &kdir, bool has_source_dir); int get_flags(const char *uname_machine, std::vector *cflags); private: std::string kdir_; bool has_source_dir_; }; int get_proc_kheaders(std::string &dir); } // namespace ebpf